이 스크립트가 어떻게 작동하는지 설명해 줄 수 있는 사람이 있나요?

이 스크립트가 어떻게 작동하는지 설명해 줄 수 있는 사람이 있나요?

파일 이름과 디렉터리 이름을 소문자로 변경하고 모든 공백을 "-"로 바꾸는 스크립트를 찾고 있습니다. 다른 스크립트에서 아래 스크립트를 찾았지만 그것이 어떻게 작동하는지 완전히 이해하지 못합니다. 누구든지 나를 안내해 주시면 매우 감사하겠습니다.

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

관련 정보