zsh: 하위 폴더의 파일 이름이 같은 경우 파일 이름 바꾸기

zsh: 하위 폴더의 파일 이름이 같은 경우 파일 이름 바꾸기

다음과 같은 파일 구조가 있습니다.

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: root 이름(csh/vim과 같이 확장자가 없는 부분...)
  • $var:h: head (csh/vim과 같은 디렉터리 이름)
  • (N): Nullglob 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.waldocharlie.waldo

관련 정보