Eu só estava tentando listar todos os diretórios e arquivos no diretório atual e também escrever se eles forem arquivo ou diretório com o seguinte comando:
find -exec echo `echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi` \;
Eu sei que é um comando bobo, posso usar outras coisas como -type f
or -type d
, mas quero saber por que esse pedaço de código não funcionou como eu esperava. Ele apenas imprime o diretório para todos eles. Por exemplo, enquanto a saída de find
é:
.
./dir
./dir/file
a saída do meu código é:
. : directory
./dir : directory
./dir/file : directory
E saída de
echo `echo dir/file : ;if [ -f dir/file ]; then echo file; else echo directory;fi`
é
dir/file : file
Estou trabalhando Ubuntu 14.10
e usandofind (GNU findutils) 4.4.2
bash
shell
find
command-substitution
Esref
fonte
fonte
find -exec bash -c 'echo -n "{} : ";if [ -f "{}" ]; then echo file; else echo directory;fi' \;
"{}"
. Por que você usaecho
duas vezes?echo "{}" : ;if [ -f "{}" ]; then echo file; else echo directory;fi
\;Respostas:
Primeiro, seu snippet executa o comando
porque precisa de sua saída para avaliar a substituição do comando. Como não há arquivo nomeado
{}
, isso produz a saídaEm seguida, o
find
comando é executado com os argumentos-exec
,echo
,{}
,:
,directory
, por isso para cada arquivo, ele exibe o nome do arquivo seguido por um espaço e: directory
.O que você realmente deseja fazer é executar o snippet de shell
echo {} :; …
em cada arquivo encontrado porfind
. Esse snippet deve ser executado por um shell geradofind
, não pelo shell iniciadofind
, pois está recebendo dados defind
sua linha de comando. Portanto, você precisa instruirfind
para executar um shell:Isso é melhor, mas ainda não está certo. Funcionará com algumas
find
implementações (não todas) se os nomes de arquivos não contiverem caracteres especiais, mas como você interpola o nome do arquivo em um script de shell, permite que os nomes de arquivos executem comandos arbitrários de shell, por exemplo, se você tiver um arquivo chamado$(rm -rf /)
então o comandorm -rf /
será executado. Para passar nomes de arquivos para o script, passe-os como argumentos separados.Além disso, o primeiro
echo
imprime uma nova linha após os dois pontos. Useecho -n
(se o seu shell suportar) ouprintf
para evitar isso.Você pode usar
-exec … {} +
para agrupar invocações de shell, o que é mais rápido.fonte
Outra maneira de executar
if; then; else; fi
juntofind
é:fonte