디렉토리에 여러 개의 파일이 있다고 가정해 보겠습니다.
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
for
bash 및 zsh 셸과 호환되는 루프를 사용하세요 .
for file in *.*; do
[ -f "$file" ] &&
mkdir -p -- "${file%.*}" &&
mv -- "$file" "${file%.*}/"
done
-p
파일이 존재하는지 확인하는 옵션이mkdir
오류를 발생시키지 않습니다.%.*
파일 이름에서 확장자를 제거하십시오.
답변4
GNU Parallel 사용(이제 막 깨닫기 시작한 도구의 강력함):
ls | parallel 'mkdir -p {.}; mv -i {} {.}'
parallel
이것은 어떤 식으로든 CPU에 국한되지 않기 때문에 속도 이점은 없을 것이라고 생각 하지만 다른 솔루션보다 여전히 짧습니다.
이는 파일 이름의 패턴에 의존하지 않습니다.