Como remover espaço em todos os subdiretórios do shell script?

6

Eu tentei seguir o shell script para remover todos os espaços com sublinhados:

find $1 -depth -name "* *" -print0 | \
while read -d $'
No such file or directory
' f; do mv -v "$f" "${f// /_}"; done

Se eu tiver um diretório /home/user/g h/y h/u j/ , ele modificará o y h directory para y_h e, em seguida, fornecerá um erro para /home/user/g h/y h/u j :

find $1 -depth -name "* *" -print0 | \
while read -d $'
No such file or directory
' f; do mv -v "$f" "${f// /_}"; done
    
por krishna 14.08.2015 / 13:56

3 respostas

5

Use isto:

find -name "* *" -print0 | sort -rz | \
  while read -d $'
find -name "* *" -print0 | sort -rz | \
  while read -d $'%pre%' f; do mv -v "$f" "$(dirname "$f")/$(basename "${f// /_}")"; done
' f; do mv -v "$f" "$(dirname "$f")/$(basename "${f// /_}")"; done

find procurará arquivos e pastas com um espaço no nome. Isso será impresso ( -print0 ) com nullbytes como delimitadores para lidar com nomes de arquivos especiais também.

O sort -rz inverte a ordem dos arquivos, para que os arquivos mais profundos de uma pasta sejam os primeiros a serem movidos e a própria pasta seja a última. Portanto, nunca há pastas renomeadas antes que todos os arquivos e pastas sejam renomeados.

Finalmente, o comando mv renomeia o arquivo / pasta. No nome do alvo, apenas removemos os espaços do nome base dos arquivos, senão não seria mais acessível.

    
por 14.08.2015 / 14:13
0
find $1 -depth -name "* *" -type d -execdir rename 's/ /_/g' "{}" \;
    
por 14.08.2015 / 14:11
0

separe entre o nome de arquivo basename (ou seja, o sobrenome no caminho) e dirname :

find $1 -depth -name "* *" -print0 | \
while read -d $'
find $1 -depth -name "* *" -print0 | \
while read -d $'%pre%' f ; do
    a="$(dirname "$f")"
    b="$(basename "$f")"
    #optional check if the basename changes -> reduces errors in mv command
    #only needed when using -wholename instead of -name in find, so skippable
    if [ "${b// /_}" != "$b" ] ; then
      mv -v "$a"/"$b"  "$a"/"${b// /_}"
    fi
done
' f ; do a="$(dirname "$f")" b="$(basename "$f")" #optional check if the basename changes -> reduces errors in mv command #only needed when using -wholename instead of -name in find, so skippable if [ "${b// /_}" != "$b" ] ; then mv -v "$a"/"$b" "$a"/"${b// /_}" fi done

O problema de primeiro alterar subdiretórios antes de alterar dirs mais altos já foi resolvido com a especificação -depth em find .

    
por 14.08.2015 / 14:05