쉘 스크립트의 모든 하위 디렉토리에서 공백을 제거하는 방법은 무엇입니까?

쉘 스크립트의 모든 하위 디렉토리에서 공백을 제거하는 방법은 무엇입니까?

밑줄 친 공백을 모두 제거하기 위해 다음 쉘 스크립트를 사용해 보았습니다.

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

디렉토리가 있으면 디렉토리가 /home/user/g h/y h/u j/수정되고 오류가 발생합니다 .y hy_h/home/user/g h/y h/u j

No such file or directory

답변1

이것을 사용하십시오 :

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

find이름에 공백이 포함된 파일 및 폴더가 검색됩니다. -print0특수 파일 이름을 처리하기 위해 널 바이트를 구분 기호로 사용하여 print() 합니다 .

sort -rz폴더의 가장 깊은 파일이 먼저 이동되고 폴더 자체가 마지막으로 이동되도록 파일 순서를 반대로 바꿉니다 . 따라서 폴더 내의 모든 파일과 폴더 이름이 바뀔 때까지는 폴더 이름이 바뀌지 않습니다.

마지막으로 이 mv명령은 파일/폴더의 이름을 바꿉니다. 대상 이름에서는 파일의 기본 이름에서 공백만 제거합니다. 그렇지 않으면 더 이상 액세스할 수 없습니다.

답변2

find $1 -depth -name "* *" -type d -execdir rename 's/ /_/g' "{}" \;

답변3

basename파일 이름(예: 경로의 성)과 다음으로 구분됩니다 dirname.

find $1 -depth -name "* *" -print0 | \
while read -d $'\0' 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

-depth상위 디렉토리를 변경하기 전에 먼저 하위 디렉토리를 변경하는 문제가 사양에서 해결되었습니다 find.

관련 정보