파일 이름과 디렉터리 이름을 소문자로 변경하고 모든 공백을 "-"로 바꾸는 스크립트를 찾고 있습니다. 다른 스크립트에서 아래 스크립트를 찾았지만 그것이 어떻게 작동하는지 완전히 이해하지 못합니다. 누구든지 나를 안내해 주시면 매우 감사하겠습니다.
find ./* -depth -type d -exec sh -c '
t=${0%/*}/$(printf %s "${0##*/}" | tr "[:upper:]" "[:lower:]");
[ "$t" = "$0" ] || mv -i "$0" "$t"
' {} \;
답변1
find ./* -depth -type d -exec sh -c ' ... ' {} \;
find
트리의 모든 디렉터리( -type d
)를 삭제하고 각 디렉터리에 대해 셸 조각을 실행하여 $0
현재 이름으로 설정합니다. -depth
각 디렉터리의 내용을 먼저 처리하고 디렉터리 자체는 마지막에 처리하도록 합니다. (그렇지 않으면 이름을 바꾸면 문제가 생길 수 있습니다.)
t=${0%/*}/$(printf %s "${0##*/}" | tr "[:upper:]" "[:lower:]");
${0%/*}
마지막 슬래시와 그 뒤의 모든 항목을 제거합니다 $0
. 즉, 디렉터리 이름을 유지합니다. ${0##*/}
기본적으로 그 반대입니다. (그들의 종류는매개변수 확장)는 printf | tr
이름의 마지막 부분을 소문자로 변경하는 데 사용됩니다. 결과는 ( 에 할당 됩니다 t
.$(...)
명령 대체)
[ "$t" = "$0" ] || mv -i "$0" "$t"
시험in의 새 이름 t
과 in의 이전 이름이 $0
동일한지 확인합니다.아니요, 그런 다음 전화 mv
를 겁니다.
여기서 어리석은 부분은 find
처럼 호출할 수 있으며 파일 이름을 찾는 작업이기 때문에 find . -depth ...
파일 이름 와일드카드( )가 필요하지 않다는 것입니다 . 대신 사용하면 파일 이름의 디렉터리 부분을 처리할 필요가 없습니다. 대상 파일 이름을 사용하는 것은 약간 잘못된 형식입니다. 이는 스크립트 자체의 이름을 의미합니다.find ./*
find
-execdir
-exec
$0
파일과 디렉터리의 이름을 바꾸고 공백을 대시로 변경하는 것에 대해 언급하셨습니다. 내가 아는 한, 여기 명령은 둘 다 수행하지 않습니다. find -type d
디렉터리만 캡처하려면 를 사용하여 -type f
일반 파일만 캡처하거나 유형을 무시하도록 남겨 두어야 합니다. 또한 에는 공백에 대한 내용이 없지만 예를 들어 모든 공백을 대시로 변경하는 등 tr
으로 변경할 수 있습니다 .tr "[:upper:][:space:]" "[:lower:][-*]"
답변2
rename
나는 많은 배포판에서 사용할 수 있는 larry wall을 사용하겠습니다 . 데비안 및 파생 제품을 포함합니다.
rename -E 's/-//g' -E 's/(.*)/\L$1/g' *
첫 번째 표현에스무엇이든 검색하고 교체하세요 -
. 두 번째 표현식은 (.*)
내용이 동일 $1
하지만 소문자로 변환된 모든 항목을 검색하고 바꿉니다.\L
답변3
제공한 스크립트는 디렉토리를 추출하여 소문자로 변경하는 작업을 수행합니다. white space
변화가 없습니다 -
.
공백을 -로 변경하고 문자열을 소문자로 변경하려면 sed가 제대로 작동합니다.
sed -e 's/[[:space:]]/-/g' -e 's/\(.*\)/\L\1/'
따라서 다음 스크립트가 작동해야 합니다.
find ./* -depth -type d -execdir sh -c '
t=$(printf %s "${1}" | sed -e 's/[[:space:]]/-/g' -e "s/\(.*\)/\L\1/")
[ "$t" = "$1" ] || echo mv -i "$1" "$t"
' sh {} \;
디렉토리 이름 추출을 방지하려면 -depth
및 를 사용하십시오 . 선택한 요소를 디렉터리로만 제한합니다 .-execdir
type d