Estou tentando usar o find
comando para listar o tamanho de um determinado conjunto de arquivos, mas não estou obtendo saída. O comando que uso é:
find POD -type f -name *.mp3 -or -name *.ogg -ls
O que não produz saída. Enquanto:
find POD -type f -name *.mp3 -or -name *.ogg
produz saída, também tentei as ações:
-printf "%p %k KB\n"
-exec ls -ls '{}' \;
-print0
mas tudo isso não fornece saída. Quando uso qualquer uma dessas ações com uma expressão diferente, por exemplo:
find . -maxdepth 1 -type f -printf "%p %k KB\n"
Eu também recebo o resultado esperado. Alguém tem alguma ideia de qual é o problema? Estou correndo:
Linux irimi 3.10.37-1-MANJARO #1 SMP Mon Apr 14 20:56:29 UTC 2014 x86_64 GNU/Linux
também conhecida como distribuição Linux Manjaro atualizada. O shell que uso é: /bin/bash
version 4.3.8(1)-release
.
O conteúdo da minha SHELLOPTS
variável de ambiente é:
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
minha BASHOPTS
variável de ambiente é:
cdspell:checkwinsize:cmdhist:complete_fullquote:dotglob:expand_aliases:extglob:extquote:force_fignore:histappend:hostcomplete:interactive_comments:nocaseglob:progcomp:promptvars:sourcepath
Novamente, qualquer ajuda para tentar depurar isso seria muito apreciada.
Responder1
Há uma armadilha com oe/oupalavras-chave em find
. or
aplicado a todos os parâmetros a seguir, incluindo a ação ( -ls
no seu exemplo). and
expressões sem or
(ou anexadas com and
) são avaliadas em ordem de leitura com uma parada final como falsa. Não há implicit ()
.
Portanto, o comando find POD -type f -name *.mp3 -or -name *.ogg -ls
significa,
- procure (começando no diretório POD) por arquivos --- se nenhum arquivo for encontrado: STOP
- else (arquivo encontrado) verifique a correspondência de padrões
*.mp3
--- se a correspondência de padrões: STOP! (porqueOR
aplicado a partir daqui e somente se o comando anterior falhou (mas apenas o comando anterior, não os grupos de comando anteriores)
e como você adiciona uma instrução de execução ( -ls
, -exec
, -print
....) na linha de comando, não há -print
comando implícito e, portanto, nada para executar se 1) todas as condições de 1) forem verdadeiras (arquivo e padrão correspondidos). Se você remover o último, -ls
haverá uma distribuição implícita -print
no final de cada condição.
- caso contrário, se o padrão não corresponder, procure por qualquer coisa (arquivo/diretório) que corresponda ao padrão
*.ogg
e liste-os (o-ls
não é um comando de condição, é executado apenas se o comando/teste "padrão" anterior*.ogg
for verdadeiro). Mas por causa de 1), 2) é avaliado apenas para arquivos NÃO mp3. Se você não tiver.ogg
arquivos, não verá nada.
Solução 1 repita o comando de execução em cada ramificação lógica
find POD -type f -name "*.mp3" -ls -or -name "*.ogg" -ls
Solução 2add (protegido pelo shell) parênteses
find POD -type f \( -name "*.mp3" -ls -or -name "*.ogg" \) -ls
Observação você deve proteger os padrões para evitar a avaliação de padrões de shell no diretório atual.
Responder2
Acho que é por causa da ordem de avaliação (falta de precedência explícita), por exemplo, se
-name '*.mp3' -o -name '*.ogg' -ls
então, se -name '*.ogg'
for avaliado como falso, a ls
ação não será executada. Você pode obter o comportamento esperado agrupando suas expressões OR usando parênteses - por exemplo, se
$ ls tests
file1.mp3 file2.mp3 file3.mp3
Então
$ find tests \( -name '*.mp3' -o -name '*.ogg' \) -print
tests/file3.mp3
tests/file1.mp3
tests/file2.mp3
enquanto
$ find tests -name '*.mp3' -o -name '*.ogg' -print
não produz saída. Observe que
$ find tests -name '*.mp3' -o -name '*.ogg'
é um caso especial porque é implicitamente tratado como
$ find tests \( -name '*.mp3' -o -name '*.ogg' \) -print
Observe também que é uma boa prática citar ou escapar dos globs do shell em um find
comando para evitar que o shell os expanda - consulte a NON-BUGS
seção da página de manual find.