我想出了這個,但不幸的是它不會影響子資料夾中的任何文件/資料夾。
find . -exec rename "s/^\s+//" {} \;
資料夾結構:
foo
|-- \ bar
`-- \ foo1
|-- \ bar1
`-- \ foo2
`-- \ bar2
答案1
重命名需要從下往上進行
問題是您需要重命名目錄從下到上。否則,該命令將嘗試重新命名已移動(重新命名)資料夾內的檔案和目錄,因此無法再找到它們。
這是可以使用python
s 的地方os.walk()
,與topdown=False
在一個小腳本中:
#!/usr/bin/env python3
import os
import shutil
import sys
for root, dirs, files in os.walk(sys.argv[1], topdown=False):
for f in files:
if f.startswith(" "):
shutil.move(root+"/"+f, root+"/"+f.strip())
for dr in dirs:
if dr.startswith(" "):
shutil.move(root+"/"+dr, root+"/"+dr.strip())
使用
- 將腳本複製到一個空文件中,另存為
no_space.py
透過命令運行它:
python3 /path/to/no_space.py /path/to/directory/to/rename
答案2
正如其他答案中所指出的,主要問題是^
錨定小路,而不是檔案名稱的開頭。有幾種方法可以使用find
and來解決這個問題rename
:可能最安全的方法是使用-execdir
來代替 ,-exec
以便所有路徑組件都減少為./
,然後替換該模式\./\s+
另外,如果您要重新命名目錄可能包括要重新命名的其他檔案/目錄的祖先,那麼你應該進行深度優先遍歷。
把它放在一起,
find . -depth -name ' *' -execdir rename -vn -- 's#\./\s+##' {} +
或(功能上等效,但更容易看到發生了什麼)使用零長度“lookbehind”作為路徑分隔符
$ find . -depth -name ' *' -execdir rename -vn -- 's#(?<=\./)\s+##' {} +
./ bar2 renamed as ./bar2
./ foo2 renamed as ./foo2
./ bar1 renamed as ./bar1
./ foo1 renamed as ./foo1
./ bar renamed as ./bar
[注意:-n
一旦您確定它能滿足您的要求,請刪除]
答案3
我認為問題在於 find 的輸出格式,其中包括完整路徑。所以對於 bar2 你將有
./ foo1/ foo2 /bar2
重命名將無法正確理解。
解決方案是使用腳本遞歸地執行每個資料夾,如下所示:
#!/bin/bash
# if argument given consider it is the directory to parse
if [ -n "$1" ]; then
cd "$1"
fi
# rename all files in current folder
find . -maxdepth 1 -printf '%f\0' | xargs -0r -n 1 rename -nono 's/^\s+//'
# No, repeat for all subfolders with current script (we are in the subfolder)
find . -maxdepth 1 -type d -not -name '.' -print0 | xargs -0r -n 1 "$(readlink -f $0)"