Aqui está outra maneira:
mkdir -p unknown;
for f in *; do
[[ $f =~ \. ]] && mkdir -p "${f##*.}" &&
mv "$f" "${f##*.}"/ ||
mv "$f" unknown/; done
Explicação
-
&&significa "executar o comando à direita apenas se o comando à esquerda for bem sucedido". -
||significa "executar o comando à direita apenas se o comando à esquerda falhar". Os dois símbolos combinados podem funcionar como um blocoif/else. -
mkdir -p unknown;: crie o diretóriounknown. O-pestá lá para quemkdirnão reclame se o diretório existir. -
for f in *: para todos os arquivos e diretórios no diretório atual. -
[[ $f =~ \. ]] &&: se o nome atual do arquivo / dir contiver um., se ele tiver uma extensão, então ... -
mkdir -p "${f##*.}"/: a construção${var##pat}removerá a correspondência mais longa depatdo início da variável$var. Aqui, opaté qualquer coisa até um ponto, então isso deixará apenas a extensão. Este comando, portanto, cria o diretório da extensão, se não existir. -
mv "$f" "${f##*.}"/: Omvmove o arquivo para o diretório relevante.|| mv "$f" unknown/;: se o comando anterior falhou (se este arquivo / diretório) não tiver uma extensão, mova-o paraunknown.
Observe que isso imprimirá essa mensagem de erro, mas você pode ignorá-la com segurança:
mv: cannot move ‘unknown’ to a subdirectory of itself, ‘unknown/unknown’
Se você precisar mover apenas arquivos e nenhum diretório (os comandos acima também moverão um diretório chamado dir.foo para foo/ ), use isso:
mkdir -p unknown;
for f in *; do
[[ -f $f ]] &&
if [[ $f =~ \. ]]; then
mkdir -p "${f##*.}" &&
mv "$f" "${f##*.}"/;
else mv "$f" unknown/; fi;
done