Você deve usar -exec
aqui:
find . \( -name '*.mp4' -o -name '*.mkv' -o -name '*.avi' \) \
-exec sh -cf 'IFS=._
for f do d=${f%/*} f=${f##*/}
[ -n "${f##*_*}" ] && continue
set -- $f
printf "%s\n" "mv \" "$d/$f \" "$d/$*"
done' find.rename.shc {} +
Como escrito, isso só imprime o comando que será executado se você prosseguir com ele. Por exemplo, a execução do acima no meu diretório .../media/Videos
imprime alguns dos itens a seguir:
mv \
/mnt/bcache/media/Videos/TV/Adventure_Time/Adventure_Time.s05e37.The_Box_Prince.mp4 \
/mnt/bcache/media/Videos/TV/Adventure_Time/Adventure.Time.s05e37.The.Box.Prince.mp4
mv \
/mnt/bcache/media/Videos/TV/Adventure_Time/Adventure_Time.s05e38.Red_Starved.mp4 \
/mnt/bcache/media/Videos/TV/Adventure_Time/Adventure.Time.s05e38.Red.Starved.mp4
Para prosseguir, você precisa mudar:
...
set -- $f
printf "%s\n" "mv \" "$d/$f \" "$d/$*"
...
... para apenas ...
...
set -- $f; mv "$d/$f" "$d/$*"
...
Em geral, você deve evitar passar nomes de arquivos e similares sobre um pipe, porque quando você faz isso, você perde os delimitadores na cabeça e cauda do nome do arquivo - ele deixa de ser um argumento e se torna uma sequência de bytes em um fluxo . A opção -exec
para find
permite reter esses delimitadores em um processo filho do processo find
em execução. Com +
, ele age como xargs
- executando o processo filho especificado apenas com a frequência necessária para evitar uma condição ARGMAX
.
Em relação ao problema sed
, você pode tentar:
LC_ALL=C xargs sed ...
Isso deve pelo menos evitar xargs
interpretando a declaração de variável de ambiente como um argumento. Não irá ajudá-lo a editar qualquer nome de arquivo, no entanto.
Uma última nota - o problema mencionado geralmente é causado por uma sequência incompleta de vários bytes ocorrendo no espaço padrão. POSIX especifica que .
não pode corresponder a parte de um caractere - e assim .*
perde seu significado naquele contexto. Forçar o C
locale deve resolvê-lo - mas outra opção para limpar espaços padrão / hold com um% GNUsed
é o comando z
.