Utilizando 'find', como posso obter 'rm' para imprimir um nome de caminho mais completo do que quando executado através de '-execdir'?

3

Resumo das Respostas : enquanto a literatura promove "-execdir" como mais segura que "-exec", não ignore a diferença operacional. O primeiro não é uma simples reimplementação do segundo. Além disso, ao usar o find especificamente para remoções interativas, a execução de "rm -f" através da opção "-okdir" também é viável. Da mesma forma para construções um pouco mais complicadas.

Estou tentando aprender o comando "find" e estou tendo problemas para entender sua saída. Peço desculpas se isso é uma duplicata, mas a declaração do problema é um pouco complicada e difícil para o Google.

Deixe-me configurar um caso de estimação: Eu começo em algum diretório (".") com dois subdiretórios "A" e "B". Em ambos, existe um arquivo chamado "hello.c."

Então, por exemplo,

find . -name "hello.c"

seria impresso assim:

./A/hello.c
./B/hello.c 

Até aí tudo bem. O que me perco é quando tento fazer algo com a opção "-execdir"; digamos que eu queira usar uma remoção interativa. Então:

find . -name "hello.c" -execdir rm -i {} \;

ou similar. O que eu espero é

rm: remove regular file "./A/hello.c"?

e, em seguida, respondendo isso, um prompt similar para o "hello.c" no diretório "B." O que realmente aparece, infelizmente, é

rm: remove regular file "./hello.c"? 

Neste pequeno exemplo, posso razoavelmente inferir que ele está perguntando sobre "./A/hello.c", mas se você aumentar esse exemplo, você terá dezenas de arquivos que terão seus nomes de caminho truncados para "./" . E eu não posso diferenciar entre dezenas de "./hello.c"s, não sem relação com o subdiretório em que cada um deles vive.

Então, minha pergunta se resume a um desejo de imprimir nomes de caminho completos via "-execdir". Eu poderia ouvir uma dica sobre qual sublety na manpage me escapou? Pouco é dito sobre a substituição "{}". Ou se houver uma maneira melhor de gerenciar esse caso específico (remoção interativa), gostaria de ouvir isso também, porque não tenho certeza se minha abordagem é a melhor prática.

    
por Kalvin Lee 16.12.2014 / 09:21

3 respostas

5

A página man do GNU find descreve -execdir em parte:

Like -exec, but the specified command is run from the subdirectory containing the matched file, which is not normally the directory in which you started find.

Portanto, não há sutileza real envolvida. -exec chama o comando do diretório em que você executa find (e, portanto, precisa fornecer o caminho relativo a esse diretório ou absoluto a partir da raiz), e -execdir chama o comando do diretório que contém o arquivo e portanto, não precisa fornecer o caminho completo, então não precisa.

Para obter o comportamento desejado, use -exec em vez de -execdir .

Você pode demonstrar esse comportamento substituindo sua invocação rm por, por exemplo, echo para simplesmente imprimir a lista de parâmetros (nesse caso, o nome do arquivo). Ou use -print , que faz isso sem precisar invocar um comando externo. (Nota: -print também é a ação padrão se nenhuma for dada.)

Se você não precisava da confirmação, poderia ter usado -delete . Para um grande número de arquivos, é provável que seja mais eficiente, já que evita ter que invocar rm vez após vez.

    
por 16.12.2014 / 09:28
2

Para ter o benefício de segurança de -execdir (que é realmente garantir que o comando não obtenha um caminho com vários componentes) e obter um prompt, você pode usar:

find . -name hello.c -okdir rm -f {} \;

(note que pelo menos a implementação GNU de find não escapa dos nomes de arquivos de uma forma adequada para terminais como o GNU rm (controle wrt, nova linha, caracteres não imprimíveis ...)).

    
por 16.12.2014 / 10:51
1

Em vez de usar -exec , que é mais simples, mas menos seguro, basta imprimir o diretório de trabalho. por exemplo,

-execdir sh -c 'pwd ; rm -i "$1"' . {} \;

Como alternativa, imprima o caminho inteiro com

-execdir sh -c 'readlink -e "$1" ; rm -i "$1"' . {} \;
    
por 16.12.2014 / 11:44

Tags