刪除檔案、資料夾及其子資料夾中的前導空格

刪除檔案、資料夾及其子資料夾中的前導空格

我想出了這個,但不幸的是它不會影響子資料夾中的任何文件/資料夾。

find . -exec rename "s/^\s+//" {} \;

資料夾結構:

foo
|-- \ bar
`-- \ foo1
    |-- \ bar1
    `-- \ foo2
        `-- \ bar2

答案1

重命名需要從下往上進行

問題是您需要重命名目錄從下到上。否則,該命令將嘗試重新命名已移動(重新命名)資料夾內的檔案和目錄,因此無法再找到它們。

這是可以使用pythons 的地方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

正如其他答案中所指出的,主要問題是^錨定小路,而不是檔案名稱的開頭。有幾種方法可以使用findand來解決這個問題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)"

相關內容