답변:
모든 디렉토리를 한 수준 또는 재귀 적으로?
한 수준에서 :
autoload zmv
zmv -o-i -Q 'root/(*)(/)' 'root/${1:l}'
재귀 적으로 :
zmv -o-i -Q 'root/(**/)(*)(/)' 'root/$1${2:l}'
설명 : zmv주어진 대체 텍스트에 따라 패턴과 일치하는 파일의 이름을 바꿉니다. 옵션을 후드 아래의 각 명령에 -o-i전달합니다 (아래 참조). 대체 텍스트에서 , 등은 패턴에서 연속 된 괄호로 묶은 그룹입니다. 재귀 적으로 모든 (하위) * 디렉토리를 의미합니다. 마지막 은 괄호로 묶은 그룹이 아니라 디렉토리와 만 일치하는 glob 한정자입니다. 소문자 로 변환 합니다.-imv$1$2**(/)${2:l}$2
한 수준에서 :
for x in root/*/; do mv -i "$x" "$(printf %s "$x" | tr '[:upper:]' '[:lower:]')"; done
마지막 /은 디렉토리와의 일치를 제한하고 mv -i충돌시 확인을 요청합니다. -i충돌시 덮어 쓰려면를 제거하고 를 사용하십시오 yes n | for …. 프롬프트되지 않고 충돌하는 이름을 바꾸지 않습니다.
재귀 적으로 :
find root/* -depth -type d -exec sh -c '
t=${0%/*}/$(printf %s "${0##*/}" | tr "[:upper:]" "[:lower:]");
[ "$t" = "$0" ] || mv -i "$0" "$t"
' {} \;
를 사용 -depth하면 깊이 중첩 된 디렉토리가 상위 항목보다 먼저 처리됩니다. 이름 처리는 /; 현재 디렉토리에서 'operate'를 호출 ./*하려면 셸 스크립트를 채택 하여 독자를위한 연습으로 남겨 .두거나 사용 *하십시오.
여기서는 데비안과 우분투가 제공하는 Perl 이름 바꾸기 스크립트를 사용합니다 /usr/bin/prename(일반적으로도 사용 가능 rename). 한 수준에서 :
rename 's!/([^/]*/?)$!\L/$1!' root/*/
bash가 ≥4 또는 zsh 인 경우 재귀 적으로 :
shopt -s globstar # only in bash
rename 's!/([^/]*/?)$!\L/$1!' root/**/*/
재귀 적으로, 이식 가능하게 :
find root -depth -type d -exec rename -n 's!/([^/]*/?)$!\L/$1!' {} +
-execdir굉장하다 : unix.stackexchange.com/questions/5412/... 나는 다음 몇 가지가 발견 PATH광기와 :-( 슬펐다
이를 수행하는 단일 명령은 없지만 다음과 같이 할 수 있습니다.
for fd in */; do
#get lower case version
fd_lower=$(printf %s "$fd" | tr A-Z a-z)
#if it wasn't already lowercase, move it.
[ "$fd" != "$fd_lower" ] && mv "$fd" "$fd_lower"
done
강력해야하는 경우에는 경우에만 다른 두 개의 디렉토리가 이미있는 경우를 고려해야합니다.
원 라이너로 :
for fd in */; do fd_lower=$(printf %s "$fd" | tr A-Z a-z) && [ "$fd" != "$fd_lower" ] && mv "$fd" "$fd_lower"; done
for file in * ; do if [ -d "$file" ] ; then dest="$(echo $file | sed y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/)" ; [ "$dest" != "$file" ] && mv "$file" "$dest" ; fi ; done
find -type d했지만 그것을 얻지 못했습니다
for fd in */;했기 때문에 디렉토리인지 확인하지 않아도되지만이 본능이 좋은지 모르겠습니다.
tr이미 범위를 기대 때문에 tr '[A-Z]' '[a-z]'변환 [에 [와 ]에 ]지나가는. 이것은 쓸모 없지만 무해합니다. 그러나 따옴표가 없으면 현재 디렉토리에 대문자 하나의 이름을 가진 파일이 있으면 쉘은 대괄호를 확장합니다.
나는 이것을 한 줄짜리 도전으로 삼았다 :) 먼저 테스트 사례를 설정하십시오.
$ for d in foo Bar eVe; do mkdir -p dcthis/$d; touch dcthis/a${d}.txt; done
$ ls dcthis/
Bar aBar.txt aeVe.txt afoo.txt eVe foo
내가 사용하는 find대문자와 디렉토리를 발견하고 그들을 통해와 downcase하기 . 사용하는 것은 약간 해킹이지만 추측 을 직접 하려고 할 때 항상 머리가 폭발 합니다.sh -c 'mv {} echo {} | tr [:upper:] [:lower:]'sh -cfind
$ (cd dcthis && find . -maxdepth 1 -type d -path '*[A-Z]*' -exec sh -c 'mv {} `echo {} | tr [:upper:] [:lower:]`' \;)
$ ls dcthis/
aBar.txt aeVe.txt afoo.txt bar eve foo
경고 :이 솔루션은 다운 케이싱으로 인해 충돌이 발생하는지 여부를 확인하지 않습니다!
mv -i. 더 큰 문제는 올바른 인용 부호를 사용하지 않았기 때문에 \[*?이름에 특수 문자 (공백 또는 ) 가 있으면 명령이 실패한다는 것 입니다. find되풀이하지 않는 한 사용의 포인트가 없으며 필요 find -depth하며 -path반드시 있어야합니다 -name. 실제 예제는 내 답변을 참조하십시오.
mv -i이것을 쓴 후에 당신 을 보았다 . 인용으로 좋은 지적 ...
find -execdir| 이름을 바꾸다
Perl 정규식 fu가 기본 이름으로 만 행동하는 것을 피하기 때문에 상대 경로 광기가 아닌 경우이 작업을 수행하는 가장 좋은 방법입니다.
PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
find a -depth -execdir rename 's/(.*)/\L$1/' '{}' \;
-execdir처음 cd에만 기본 이름에 실행하기 전에 디렉토리에이야.
불행히도, 나는 그 PATH해킹 부분을 제거 할 수 없으며 find -execdir상대 경로가 있다면 아무것도하지 않습니다 PATH: /ubuntu/621132/why-using-the-execdir-action- 경로에있는 디렉토리의 안전하지 않은 보안 / 1109378 # 1109378
mv -i a a"mv : a를 a / a로 변경 : Invalid argument".