localizar e sed (localizar e substituir) causa sequência de bytes inválida no Mac OS X

2

Eu estou tentando executar uma localização e substituição de sublinhados em pontos em um diretório apenas para determinados tipos de arquivos (.mkv, .mp4, .avi). Este é o código que estou usando (estou no Mac OS X 10.9):

find . \( -name '*.mp4' -o -name '*.mkv' -o -name '*.avi' \) -print0 | 
    xargs -0 sed -i '' -e 's/\./_/g'

Eu li sobre duas soluções, ambas que não funcionaram.

Primeiro, adicionei o seguinte ao meu ~ / .bash_profile:

export LC_CTYPE=C 
export LANG=C

Isso causou o mesmo erro, então tentei usar:

LC_ALL=C sed ... 

e isso não funcionou, recebi este erro:

xargs: LC_ALL=C: No such file or directory

Alguma outra sugestão? Sou novo em shell.

EDITAR: Isso é o que estou tentando realizar:

Estou tentando passar por um diretório e substituir os sublinhados nos nomes dos arquivos por pontos.

Exemplo:

random_movie.mp4 deve ser random.movie.mp4

    
por Yashar 26.11.2014 / 04:49

1 resposta

0

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 .

    
por 26.11.2014 / 08:08

Tags