xargs
é a ferramenta para o trabalho. Isso, ou find
com -exec … {} +
. Essas ferramentas executam um comando várias vezes, com tantos argumentos quanto podem ser passados de uma só vez.
Ambos os métodos são mais fáceis de executar quando a lista de argumentos variáveis está no final, o que não é o caso aqui: o argumento final para mv
é o destino. Com os utilitários GNU (ou seja, no Linux ou Cygwin não integrado), a opção -t
para mv
é útil para passar primeiro o destino.
Se os nomes dos arquivos não tiverem espaço em branco nem \"'
, você poderá simplesmente fornecer os nomes dos arquivos como entrada para xargs
(o comando echo
é um bash incorporado, portanto, não está sujeito à limite de comprimento da linha de comando):
echo !(*.jpg|*.png|*.bmp) | xargs mv -t targetdir
Você pode usar a opção -0
para xargs
para usar a entrada delimitada por nulo em vez do formato padrão entre aspas.
printf '%sfind . -name . -o -type d -prune -o \
-name '*.jpg' -o -name '*.png' -o -name '*.bmp' -o \
-exec mv -t targetdir/ {} +
' !(*.jpg|*.png|*.bmp) | xargs -0 mv -t targetdir
Como alternativa, você pode gerar a lista de nomes de arquivos com find
. Para evitar recursão em subdiretórios, use -type d -prune
. Como nenhuma ação é especificada para os arquivos de imagem listados, apenas os outros arquivos são movidos.
find . -name . -o -type d -prune -o \
-name '*.jpg' -o -name '*.png' -o -name '*.bmp' -o \
-exec sh -c 'mv "$@" "$0"' targetdir/ {} +
(Isso inclui arquivos de pontos, diferente dos métodos de curingas de shell).
Se você não tem utilitários GNU, você pode usar um shell intermediário para obter os argumentos na ordem correta. Este método funciona em todos os sistemas POSIX.
setopt extended_glob
zmodload zsh/files
mv -- ^*.(jpg|png|bmp) targetdir/
No zsh, você pode carregar o mv
builtin :
setopt extended_glob
zmodload -Fm zsh/files b:zf_\*
zf_mv -- ^*.(jpg|png|bmp) targetdir/
ou se preferir deixar mv
e outros nomes se referirem aos comandos externos:
setopt ksh_glob
zmodload -Fm zsh/files b:zf_\*
zf_mv -- !(*.jpg|*.png|*.bmp) targetdir/
ou com globs de estilo ksh:
autoload -U zargs
setopt extended_glob
zargs -- ./^*.(jpg|png|bmp) -- mv -t targetdir/
Como alternativa, usar o GNU mv
e zargs
:
echo !(*.jpg|*.png|*.bmp) | xargs mv -t targetdir