Você pode usar find
para encontrar todos os arquivos em uma árvore de diretórios que correspondam (ou não jogo) alguns testes particulares e, em seguida, fazer algo com eles. Para este problema em particular, você poderia usar:
find -type f ! \( -iname '*.png' -o -iname '*.gif' -o -iname '*.jpg' -o -iname '*.xcf' \) -exec echo mv {} /new/path \;
Isso limita a pesquisa a arquivos regulares ( -type f
) e, em seguida, a arquivos cujos nomes não ( !
) têm a extensão *.png
em qualquer caixa ( -iname '*.png'
) ou ( -o
) *.gif
e assim por diante. Todas as extensões são agrupadas em uma única condição entre \( ... \)
. Para cada arquivo correspondente, ele executa um comando ( -exec
) que move o arquivo, cujo nome é inserido no lugar de {}
, no diretório /new/path
. O \;
informa find
que o comando acabou.
A substituição de nomes acontece dentro do código de execução do programa, portanto, espaços e outros caracteres especiais não importam.
Se você quiser fazer isso apenas dentro do Bash, é possível usar a correspondência de padrões estendida do Bash recursos . Eles exigem que shopt extglob
esteja ativado e globstar
também. Neste caso, use:
mv **/!(*.[gG][iI][fF]|*.[pP][nN][gG]|*.[xX][cC][fF]|*.[jJ][pP][gG]) /new/path
Isso corresponde a todos os arquivos em subdiretórios ( **
) que não correspondem a *.gif
, *.png
, etc, em qualquer combinação de casos de caractere e os move para o novo caminho. A expansão é executada pelo shell, portanto, espaços e caracteres especiais não importam novamente.
O acima assume que todos os arquivos estão em subdiretórios. Se não, você pode repetir a parte depois de **/
para incluir o diretório atual também.
Existem recursos semelhantes em zsh
e em outros shells, mas você ve indicou que você está usando Bash.
(Uma observação adicional: analisar ls
nunca é uma boa ideia - apenas não tente.)