Como encontrar vários arquivos no sistema linux

3

Eu tenho muitos arquivos no meu sistema e cada arquivo tem um nome de arquivo correspondente. Por exemplo,

test.pdf tem test-project.zip test2.pdf tem test2-project.zip

test.pdf e test2.pdf são os arquivos originais e test-project.zip e test2-project.zip são gerados pelo meu script.

Eu preciso descobrir se todos os meus arquivos originais têm o 'filename'-project.zip correspondente ao arquivo original.

Eu posso usar

find /project/ -name "*.pdf" | wc -l
find /project/ -name "*-project.zip" | wc -l

para descobrir se os números correspondem, mas preciso saber qual arquivo não tem arquivo correspondente.

Alguém pode me ajudar sobre isso? Muito obrigado!

    
por FlyingCat 24.05.2013 / 21:10

2 respostas

5

Script rápido, adapte como achar melhor:

#!/usr/bin/env bash

find /project/ -name '*.pdf' -print0 | while read -d $'
[ -e "${i/%.pdf/-project.zip}" ] || echo "${i/%.pdf/-project.zip} doesn't exist!"
' i; do if [ ! -e "${i/%.pdf/-project.zip}" ]; then echo "${i/%.pdf/-project.zip} doesn't exist!" fi done exit 0

-d $'read' define o delimitador de -print0 como nullbyte, enquanto find é equivalente a ${i/%.pdf/-project.zip} , portanto, deve ser à prova de balas em arquivos com espaços e novas linhas em seus nomes (obviamente irrelevantes neste caso, mas útil saber em geral). .pdf substitui o $i no final da variável -project.zip com if . Fora isso, tudo isso é um script padrão de shell.

Se você quiser encurtá-lo ainda mais, você também pode usar

#!/usr/bin/env bash

shopt -s globstar
for f in /project/**/*.pdf; do
  if [ ! -e "${f/%.pdf/-project.zip}" ]; then
    echo "${f/%.pdf/-project.zip} doesn't exist!"
  fi
done

exit 0

... em vez da instrução if . Eu acho que if é mais fácil de trabalhar se você estiver usando mais do que uma única linha curta (você pode contornar isso usando uma função, mas nesse ponto você não está recebendo nenhum psace salvando vs. bash --version ).

Supondo que você tenha 4++ (provavelmente você faz; você pode verificar com find ), você pode usar a opção globstar em vez de %code% :

#!/usr/bin/env bash

find /project/ -name '*.pdf' -print0 | while read -d $'
[ -e "${i/%.pdf/-project.zip}" ] || echo "${i/%.pdf/-project.zip} doesn't exist!"
' i; do if [ ! -e "${i/%.pdf/-project.zip}" ]; then echo "${i/%.pdf/-project.zip} doesn't exist!" fi done exit 0

Isto tem a vantagem de ser puro bash, por isso deve ser mais rápido (apenas notavelmente com pelo menos centenas de arquivos, no entanto).

    
por 24.05.2013 / 21:46
0

Aqui estão duas maneiras de fazer isso. Um deles é um one-liner do Bash que gera pelo menos um, possivelmente dois, processos para cada arquivo correspondente:

[me@box] $ for file in 'find -name '*.pdf' -exec perl -le'$f=shift(); $f =~ s@\.pdf$@@; print $f' {} \;'; do (TESTFILE="$file-project.zip"; if [ ! -f $TESTFILE ]; then echo "missing $TESTFILE"; fi); done

Já que isso é suficiente para fazer os olhos de qualquer um sangrar, aqui está um script em Perl que faz o mesmo trabalho, muito mais do que qualquer script Bash poderia:

#!/usr/bin/env perl
use strict;

my $path = shift() || die "$0 requires a path argument\n";
my @files = 'find "$path" -name '*.pdf'';

foreach my $file (@files) {
  chomp $file;
  my $zip = $file;
  $zip =~ s@\[email protected]@;
  next if -f $zip;
  print "missing $zip\n";
};

Copie isso para, por exemplo, "find-missing.pl" e invoque find-missing.pl /project/ .

    
por 24.05.2013 / 21:50