![扁平化資料夾結構](https://rvso.com/image/36020/%E6%89%81%E5%B9%B3%E5%8C%96%E8%B3%87%E6%96%99%E5%A4%BE%E7%B5%90%E6%A7%8B.png)
我有這個資料夾結構:
├── foo1
│ ├── bar1.txt
│ └── bar2.txt
├── foo2
│ ├── bar3.txt
│ └── bar4 with a space.txt
└── foo3
└── qux1
├── bar5.txt
└── bar6.txt
我想將其扁平化,在每個資料夾層級之間使用下劃線:
├── foo1_bar1.txt
├── foo1_bar2.txt
├── foo2_bar3.txt
├── foo2_bar4 with a space.txt
├── foo3_qux1.bar6.txt
└── foo3_qux1_bar5.txt
我環顧四周,沒有找到任何有效的解決方案,主要是因為我的問題有兩個特殊性:根資料夾內可能有多個資料夾級別,而且有些文件可能有空格。
知道如何在 bash 中實現這一點嗎?謝謝!
編輯:運行格倫傑克曼提出的答案我得到這個:
一級資料夾有兩個底線。知道如何避免這種情況或只是重命名它,以便這只是一個下劃線嗎?謝謝。
答案1
find */ -type f -exec bash -c 'file=${1#./}; echo mv "$file" "${file//\//_}"' _ '{}' \;
echo
如果您對它的工作感到滿意,請將其刪除。不要擔心 echo 命令不顯示引號,腳本將正確處理帶有空格的檔案。
如果您想要刪除現在空的子目錄:
find */ -depth -type d -exec echo rmdir '{}' \;
答案2
使用perl的重命名:
find . -depth -type f -exec rename 's@(?<!\.)/@_@g' -- {} \;
輸出
$ find -type f
./foo2_bar4 whit a space.txt
./foo3_qux1_bar6.txt
./foo2_bar3.txt
./foo3_qux1_bar5.txt
./foo1_bar2.txt
./foo1_bar1.txt
筆記
- 我用一個消極地向後看
(?<!\.)
不要碰第一個./
我保留空目錄,請隨意:
find . -depth -type d -exec rm {} \;
還有其他同名的工具可能能夠也可能無法做到這一點,所以要小心。
如果執行以下命令 ( GNU
)
$ file "$(readlink -f "$(type -p rename)")"
你有一個像這樣的結果
.../rename: Perl script, ASCII text executable
且不包含:
ELF
那麼這似乎是正確的工具 =)
如果不是,則將其設為預設值(通常已經是這種情況)Debian
並衍生如下Ubuntu
:
$ sudo update-alternatives --set rename /path/to/rename
(替換為您的命令/path/to/rename
的路徑。perl's rename
如果您沒有此命令,請搜尋套件管理器來安裝它或手動做
最後但並非最不重要的一點是,這個工具最初是由 Perl 之父 Larry Wall 編寫的。
答案3
和pax
…
pax -Xrwls '|/|_|g' */ "$PWD"
這將在當前目錄中創建一個指向其子目錄中所有文件的硬鏈接,_
並將/
.然後您可以檢查結果並使用以下命令刪除所有子目錄...
rm -rf */
……一旦您確認結果符合您的喜好。
答案4
您可以嘗試使用以下命令。
$ find -type f -exec bash -c 'mv $0 $(echo $0|sed "s/\//_/2")' {} \;
上述命令將移動文件,並且目錄將保留,稍後可以刪除。
$ ls
foo1_bar1.txt foo1_bar2.txt foo2_bar3.txt foo2_bar4.txt foo3_bar5.txt foo3_bar6.txt