簡體   English   中英

使用regex重命名linux中的文件

[英]Rename files in linux with regex

這實際上不是問題,我自己解決了。 但是我想在這里發布我的解決方案,以在相同情況下節省其他人的時間和精力。

因此,我不得不重新命名很多(+3000)以匹配特定模式的情況。 在我的情況下,文件是同步的自動備份,因此文件將被重命名,如下所示:

foo.bar -> foo~20150221-1330.bar

經過大量的論壇和手冊頁搜索后,我創建了以下單行代碼,該代碼使用linux中的find, sedxargsmv命令恢復了原始文件名:

find . -type f  | sed -e 'p;s/\(.*\)~20[0-9]\{6\}-[0-9]\{6\}\(.*\)/\1\2/' | xargs -n2 -d'\n' mv

如果您願意,可以用自己的樣式替換sed -part。 該命令可以通過空格(由於xargs-d'\\n'標志)來處理空格,但不能使用換行符。 我希望某些人覺得此命令有用。

好的,我將為每個命令提供更多信息:

  • find :給出當前目錄中的所有常規文件(不是目錄)
  • sedp將打印stdin中的每一行, s/regex/regex/將打印相同的行,但是被替換。 因此,您得到每個文件后跟固定的文件名:

     ./foo/bar~20150221-172703.txt ./foo/bar.txt` 
  • xargs-n2將使用兩行並將其作為參數發送到mv ,-d'\\ n'將解決文件夾名稱中的空格問題(定界符設置為換行符而不是空格)

您的回答很好,但是如果您還想處理還包含換行符的文件名,或者您不想使用sed並且要確保僅考慮具有與該模式匹配的基本名稱的文件(您的方法失敗,例如,使用dir~20150221-172703/file ,並且當文件名與您的模式不匹配時,您的方法使mv抱怨filefile是同一文件),您需要稍作不同。


一種可能的情況是,如果您的find支持-print0選項(GNU find則支持):讓find吐出所有文件名,並使用while循環,其中Bash(未sed )將執行替換。 像這樣:

find . -type f -print0 | while IFS= read -r -d '' file; do
    dirname=${file%/*}
    basename=${file##*/}
    # Perform the substitution only on basename
    # Since you like regex, you can use them
    if [[ $basename =~ ^(.*)~20[0-9]{6}-[0-9]{6}(.*)$ ]]; then
        new_basename=${BASH_REMATCH[1]}${BASH_REMATCH[2]}
        echo mv "$dirname/$basename" "$dirname/$new_basename"
    fi
done

您還可以通過使用-regex過濾器(不是POSIX,但GNU find支持它)來確保只find匹配文件。

find . -regextype posix-basic -regex '.*~20[0-9]\{6\}-[0-9]\{6\}[^/]*' -type f

不確定是否可以完全回答您的問題,但至少可以解決您的方法所存在的缺陷。

沒有GNU好吃的東西,要擁有堅固而干凈的東西就更加困難了。

您可以使用rnm

rnm -rs '/(.*)~20[0-9]{6}-[0-9]{6}(.*)/\1\2/' -fo -dp -1 *
  1. -fo :僅文件模式
  2. -dp :目錄深度(-1表示無限深度,即轉到所有子目錄)。

不過,您可以完全使用自己的正則表達式模式,在這種情況下,您必須將正則表達式模式更改為基本(BRE):

rnm --regex basic -rs '/\(.*\)~20[0-9]\{6\}-[0-9]\{6\}\(.*\)/\1\2/' -fo -dp -1 *

注意:

  1. 只有無效字符是空字符和路徑定界符( / )。
  2. 默認正則表達式模式為javascript。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM