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 incorporado), a -t
opção to mv
é útil para passar o destino primeiro.
Se os nomes dos arquivos não tiverem espaço em branco nem nenhum \"'
, você poderá simplesmente fornecer os nomes dos arquivos como entrada xargs
(o echo
comando é um bash integrado, portanto, não está sujeito ao limite de comprimento da linha de comando):
echo !(*.jpg|*.png|*.bmp) | xargs mv -t targetdir
Você pode usar a -0
opção para xargs
usar entrada delimitada por nulo em vez do formato entre aspas padrão.
printf '%s\0' !(*.jpg|*.png|*.bmp) | xargs -0 mv -t targetdir
Como alternativa, você pode gerar a lista de nomes de arquivos com find
. Para evitar a 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 mv -t targetdir/ {} +
(Isso inclui arquivos de ponto, ao contrário dos métodos curinga do shell.)
Se você não possui utilitários GNU, pode usar um shell intermediário para obter os argumentos na ordem correta. Este método funciona em todos os sistemas POSIX.
find . -name . -o -type d -prune -o \
-name '*.jpg' -o -name '*.png' -o -name '*.bmp' -o \
-exec sh -c 'mv "$@" "$0"' targetdir/ {} +
No zsh, você pode carregar o mv
builtin :
setopt extended_glob
zmodload zsh/files
mv -- ^*.(jpg|png|bmp) targetdir/
ou se você preferir permitir mv
e outros nomes continuem se referindo aos comandos externos:
setopt extended_glob
zmodload -Fm zsh/files b:zf_\*
zf_mv -- ^*.(jpg|png|bmp) targetdir/
ou com globs no estilo ksh:
setopt ksh_glob
zmodload -Fm zsh/files b:zf_\*
zf_mv -- !(*.jpg|*.png|*.bmp) targetdir/
Como alternativa, usando GNU mv
e zargs
:
autoload -U zargs
setopt extended_glob
zargs -- ./^*.(jpg|png|bmp) -- mv -t targetdir/