폴더의 모든 파일을 같은 이름의 하위 디렉터리로 이동하는 방법은 무엇입니까?

폴더의 모든 파일을 같은 이름의 하위 디렉터리로 이동하는 방법은 무엇입니까?

디렉토리에 여러 개의 파일이 있다고 가정해 보겠습니다.

filename-1.ext1
filename-1.ext2
filename-1.ext3
filename-2.ext1
filename-2.ext2
filename-2.ext3
filename-3.ext1
filename-3.ext2
filename-3.ext3

그런 다음 파일(파일 이름은 있지만 확장자는 없음)과 동일한 이름의 동일한 디렉토리에 하위 디렉토리를 만들고 다음과 같이 이동하려고 합니다.

filename-1
├──filename-1.ext1
├──filename-1.ext2
└──filename-1.ext3
filename-2
├──filename-2.ext1
├──filename-2.ext2
└──filename-2.ext3
filename-3
├──filename-3.ext1
├──filename-3.ext2
└──filename-3.ext3

이를 달성하는 가장 효율적인 방법은 무엇입니까?

편집: ext1, ext2, ext3은 .foo, .bar, .top, .coffee 등과 같은 세 가지 고유한 파일 이름을 나타 내기 위한 것입니다. 파일 이름이 비슷한 것은 아닙니다.

답변1

를 사용하고 있으므로 zsh다음과 같이 수행할 수 있습니다.

for name (*.ext<->(.)) mkdir -p -- $name:r && mv -- $name $name:r 

또는 더 친숙한 긴 형태의 루프를 사용 for하여

for name in *.ext<->(.); do
    mkdir -p -- $name:r &&
    mv -- $name $name:r
done

*.ext<->이는 임의의 숫자 와 일치하는 패턴과 일치하는 모든 일반 파일을 반복합니다 <->. (.)일반 파일만 일치하도록 강제하는 glob 한정자입니다 . *.*(.)점이 포함된 일반 파일의 파일 이름과 일치시키려면 전체 패턴을 다음으로 변경하십시오 . 나중에 파일 이름 확장자를 제거하려면 점이 있어야 합니다. 느슨한 패턴보다는 더 엄격한 패턴을 사용하려면 다음과 같은 것을 사용하세요 filename-<->.ext<->(.). 이 패턴을 사용하려면 문자열로 시작하는 이름을 일치시키려는지 알아야 합니다 filename-.

확장 $name:r하면 와 동일한 값이 생성되지만 $name확장자는 없습니다(즉, 값의 "루트"만).

우리는 --두 옵션 모두에 옵션의 끝을 알리고 대시로 시작하는 이름이 옵션으로 오인되는 것을 방지하기 위해 mkdir사용 합니다.mv

답변2

와 함께 zmv:

autoload -Uz zmv # best in ~/.zshrc
mkmv() { mkdir -p -- $2:h && mv -- "$@"; }

zmv -P mkmv -n '(*).ext<->(#q.)' '$1/$f'

(만족하면 제거 -n).

그렇게 하면 zmv의 건전성 검사로부터 이익을 얻을 수 있습니다.

답변3

forbash 및 zsh 쉘 모두와 호환되는 이 루프를 사용하십시오 .

for file in *.*; do
  [ -f "$file" ] &&
    mkdir -p -- "${file%.*}" &&
    mv -- "$file" "${file%.*}/"
done
  • -p옵션을 사용하면 mkdir파일이 존재하는지 확인합니다. 오류가 발생하지 않습니다.
  • %.*파일 이름에서 확장자를 제거합니다.

답변4

GNU 병렬(제가 이제 막 그 강력함을 깨닫기 시작한 도구)을 사용하면 다음과 같습니다.

ls | parallel 'mkdir -p {.}; mv -i {} {.}'

이것은 어떤 식으로든 CPU에 국한되지 않기 때문에 parallel속도상의 이점을 제공하지는 않지만 다른 솔루션보다 여전히 짧습니다.

그리고 이것은 파일 이름의 패턴에 의존하지 않습니다.

관련 정보