다음과 같은 파일 구조가 있습니다.
charlie
├──this-file.foo.1
├──this-file.foo.2
└──this-file.foo.3
foxtrot
├──another-file.foo.1
├──another-file.foo.2
├──another-file.foo.3.bar
├──another-file.foo.4.baz
└──another-file.foo.5.qux
this-file.waldo
another-file.waldo
루트 폴더에 있는 모든 파일의 이름을 바꾸고 싶습니다. 이 경우 this-file.waldo
에는 another-file.waldo
. 하위 폴더에 .waldo 파일과 동일한 기본 이름을 가진 파일이 있는 경우 다음과 같이 이름이 같은 하위 폴더의 이름을 사용하여 .waldo 파일의 이름을 바꾸고 싶습니다.
charlie
├──this-file.foo.1
├──this-file.foo.2
└──this-file.foo.3
foxtrot
├──another-file.foo.1
├──another-file.foo.2
├──another-file.foo.3.bar
├──another-file.foo.4.baz
└──another-file.foo.5.qux
charlie.waldo
foxtrot.waldo
하위 폴더에 동일한 기본 이름을 공유하는 파일이 있고 하위 폴더와 동일한 이름으로 이름을 바꿔야 하는 경우에만 파일 이름을 바꿔야 합니다.
이를 달성하는 가장 효율적인 방법은 무엇입니까?
- 항상 .waldo 파일이 있습니다.
- 기본 이름을 공유하는 파일이 없으면 무시하고 일치하는 항목을 찾을 때까지 다음 파일로 진행해야 합니다.
- 파일 이름은 일반 OS 파일 이름이므로 &()[]# 등이 있을 수 있습니다.
답변1
그것은 다음과 같을 수 있습니다:
for f (*.waldo(N)) (){ (($#)) && echo mv -- $f $1:h.waldo; } */$f:r.*(NY1)
( echo
만족스러운 경우 (시험 실행)을 제거하십시오).
덜 일반적인 zsh 기능 중 일부는 다음과 같습니다.
for f (values) action
: for 루프의 짧은 형식(perl 구문과 유사)() { body; } args
: 익명 함수$var:r
:r
oot 이름(csh/vim과 같이 확장자가 없는 부분...)$var:h
:h
ead (csh/vim과 같은 디렉터리 이름)(N)
:N
ullglob glob qualifier: 일치하는 항목이 없어도 오류를 보고하지 않습니다.(Y1)
: 첫 번째 일치 글로벌 한정자 이후에 중지됩니다.
답변2
먼저 현재 디렉터리의 모든 파일 목록을 얻습니다.
files=(*(.DoN))
그런 다음 각 항목에 대해 다음과 같은 작업을 수행합니다.
for file in $files; do
# get the basename
bname="${file%%.*}"
# look for matches in subfolders
typeset -a matches_in_subfolders
matches_in_subfolders=*/${bname}*
# Check whether list of matches is longer than 0
if [ ${#matches_in_subfolders[@]} -gt 0 ] ; then
# do your magic renaming here
fi
done
여러 결과를 처리하는 방법을 잘 모르기 때문에 여기서 이름을 바꾸지는 않았지만
mv -- "${file}" "${matches_in_subfolders[0]}${file#*.}"
file
이름은 해당 폴더가 포함된 첫 번째 폴더의 이름과 가장 긴 확장자로 이름이 변경됩니다 (만약 가 아닌 .waldo
경우에는 가 아닌 을 .foo.waldo
원한다고 가정합니다 ).charlie.foo.waldo
charlie.waldo