Como usar os resultados de “file” (Nome da criação de aplicativos: Microsoft Word) para procurar uma string específica?

4

Eu estou tentando usar os resultados de "arquivo", que retorna informações sobre o arquivo / s que eu especificar.

Por exemplo,

file *.doc 'all .doc extensions

Isso, em seguida, retorna informações sobre o arquivo, incluindo "Nome da criação de aplicativos: Microsoft Word" Agora, estou tentando pesquisar os resultados para a seqüência de caracteres "Word". Estou preso aqui. Como eu realmente faço isso?

* Isso é o que eu tentei depois de horas de pesquisa. Eu só não sei qual palavra eu estou procurando. Por favor, informe.

find . -type f -print0 | xargs -0 grep -lh "Microsoft Word" | xargs -I % mv % ../NewDirectory/

Acho que isso procura a string "Word" dentro dos próprios arquivos e os move para o novo diretório.

    
por A. Mist 29.09.2015 / 10:04

2 respostas

2

Se bem entendi, você deseja mover os arquivos do diretório atual e de seus subdiretórios recursivamente para outro diretório, mas somente se o comando file os relatar como arquivos "Microsoft Word". Ou seja, você está interessado nos arquivos para os quais file "$filename" | grep 'Microsoft Word' produz alguma saída.

Uma maneira fácil é levar as coisas com calma e arquivar por arquivo. Se você quiser apenas os arquivos no diretório atual, poderá usar um loop for e um padrão curinga:

for f in *.doc; do
  if …
done

Qual é a condição? Queremos testar se Microsoft Word aparece na saída de file "$f" . Eu uso file -- para proteger contra arquivos cujo nome começa com - .

for f in *.doc; do
  if file -- "$f" | grep -s 'Microsoft Word'; then
    …
  fi
done

Tudo o que precisamos fazer é adicionar o comando para mover os arquivos.

for f in *.doc; do
  if file -- "$f" | grep -s 'Microsoft Word'; then
    mv -- "$f" ../NewDirectory/
  fi
done

Se você quiser procurar arquivos em subdiretórios também, use o ** padrão wilcdard para globalização recursiva. No bash, ele precisa ser ativado com shopt -s globstar (em ksh93, você precisa de set -o globstar e, em zsh, funciona fora da caixa; outros shells não possuem esse recurso). Cuidado que bash ≤4.2 segue links simbólicos para diretórios.

for f in **/*.doc; do
  if file -- "$f" | grep -s 'Microsoft Word'; then
    mv -- "$f" ../NewDirectory/
  fi
done

Observe que todos os arquivos movidos terminam em ../NewDirectory/ , nenhum subdiretório é criado. Se você quiser reproduzir a árvore de diretórios, use construções de manipulação de string para extrair a parte do diretório do nome do arquivo e mkdir -p para criar o diretório de destino, se necessário.

for f in ./**/*.doc; do
  if file "$f" | grep -s 'Microsoft Word'; then
    d="${f%/*}"
    mkdir -p ../NewDirectory/"$d"
    mv "$f" ../NewDirectory/"$d"
  fi
done

Em vez de analisar a saída de file , que é um pouco frágil, talvez você prefira analisar file -i , que imprime strings padronizadas.

    
por 30.09.2015 / 03:03
2

Seu primeiro exemplo file não funcionará devido à cotação única incomparável, mas acho que você já encontrou isso por causa do seu segundo exemplo.

Se você fizer isso:

find . -type f

você pode ver a saída. Esses são nomes de arquivos. Se você quiser selecionar algo dessa saída, use grep diretamente

find . -type f  |  grep "Microsoft Word"

que pesquisa nos nomes de arquivos, não no conteúdo dos arquivos listados. Isso não é totalmente preciso, pois um nome de arquivo pode ter uma nova linha, tornando a saída incompleta se um nome de arquivo com "Microsoft Word" contiver uma nova linha como parte do nome.

Se você fizer isso:

find . -type f -print0 | xargs -0 grep -lh "Microsoft Word" 

a parte xargs realmente entrega os nomes dos arquivos ao grep (o -print0 para find e -0 para xargs é para manipular o nome do arquivo com novas linhas). Isso procura por toda a string "Microsoft Word" e não apenas "Word" nos arquivos .

O -lh especificado para grep lista os nomes dos arquivos, e pode haver um problema com isso, pois novas linhas em nomes de arquivos são impressas normalmente, você deve continuar a usar nomes de arquivos terminados em NUL especificando -Z também. Se você não especificar -l , também obterá o conteúdo das correspondências de linhas, o que tornaria o processamento adicional (seu mv ) impossível.

Se você quiser mover todos os arquivos para um diretório, geralmente é mais fácil usar mv -t em vez de mucking com xargs ' -I option (o que permite colocar os parâmetros xargs reads de sua entrada em um lugar diferente do que o final de linha padrão, mas que é mais lento que mv é chamado uma vez para cada arquivo):

find . -type f -print0 | xargs -0 grep -lhZ "Microsoft Word" | xargs -0 mv -t ../NewDirectory/

E isso move todos os arquivos para algum lugar no diretório atual, com o "Microsoft Word" em parte de seu conteúdo para o NewDirectory que está ao lado do diretório atual. Por favor, note que ../NewDirectory tem que existir.

    
por 29.09.2015 / 10:25