如何將資料夾中的每個檔案移動到同名的子目錄中?

如何將資料夾中的每個檔案移動到同名的子目錄中?

假設我的目錄中有一堆文件

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 shell 相容的循環:

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不會帶來任何速度優勢,但它仍然比許多其他給定的解決方案短。

這不依賴檔案名的模式。

相關內容