xargsé a ferramenta para o trabalho. Isso ou findcom -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 -topçã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 echocomando é 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 -0opção para xargsusar 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 mvbuiltin :
setopt extended_glob
zmodload zsh/files
mv -- ^*.(jpg|png|bmp) targetdir/
ou se você preferir permitir mve 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 mve zargs:
autoload -U zargs
setopt extended_glob
zargs -- ./^*.(jpg|png|bmp) -- mv -t targetdir/