Como "pegar" arquivos correspondentes de um arquivo de pesquisa no bash?

1

Eu tenho um arquivo de pesquisa contendo nomes de arquivos. Eu também tenho um diretório contendo arquivos, alguns dos quais têm os nomes que correspondem a alguns dos nomes no diretório.

Como posso:

  1. Mover arquivos de correspondência exata para um novo diretório ou
  2. Remover arquivos não correspondentes do diretório existente

Além disso, como posso fazer isso de forma recursiva por meio de um diretório de nível superior e de seus subdiretórios?

    
por user31333 28.01.2013 / 16:58

2 respostas

1

Talvez algo nas seguintes linhas:

sed -e 's;^.*$;\^&\$; list-of-names > list-of-patterns

rm $(find . -type f | grep -v -f list-of-patterns)

Tenha cuidado, isso certamente irá quebrar se os nomes dos arquivos contiverem espaços ou caracteres que o shell considera especiais. Por favor, verifique o que isso excluiria antes de executá-lo de verdade!

(Pode haver uma maneira de contornar o arquivo de padrão, mas eu não vejo isso).

    
por 28.01.2013 / 17:26
1

O seguinte script bash (aviso: não testado!) move os arquivos de /directory/with/the/files para /matched/files . Somente arquivos cujo nome (sans directory) está em /path/to/lookup.file são movidos. Observe que se houver links simbólicos para diretórios em /directory/with/the/files , eles serão percorridos recursivamente como se fossem diretórios.

#!/bin/bash
shopt -s globstar
set -f; IFS=$'\n'
typeset -A filenames
for x in $(cat /path/to/lookup.file); do filenames[$x]=1; done
set +f; unset IFS
cd /directory/with/the/files
for x in ./**; do
  if [[ -d "$x/." ]]; then
    : # skip directories and symbolic links to directories
  elif [[ -n ${filenames[${x##*/}]} ]]; then
    # the file is matched, move it under /matched/files
    mkdir -p "/matched/files/${x%/*}"
    mv "$x" "/matched/files/$x"
  else
    # the file isn't matched
    :
  fi
done

Explicações:

  • shopt -s globstar permite que o ** glob atravesse diretórios recursivamente.
  • set -f; IFS=$'\n' desativa a globulação e define novas linhas como o único delimitador de palavras, de forma que a substituição de comando sem aspas $(cat /path/to/lookup/files) seja dividida apenas em novas linhas.
  • filenames é uma matriz associativa .
  • for x in ./** cuida que $x sempre contém uma parte do diretório (dessa forma, ${x%/*} é a parte do diretório $x , com . para o diretório de nível superior) e não começa com - (por isso não corre o risco de ser tratado como uma opção).
  • ${x##*/} expande para a parte do nome do arquivo de $x , ou seja, $x sem a parte do diretório.
por 29.01.2013 / 01:08