Bash

將 bash 腳本中的文件移動到從文件名中提取的子目錄

  • November 9, 2021

我有一個包含一堆備份文件的目錄,如下所示:

projectA20210901.gz
projectA20210902.gz
projectB20210901.gz
projectB20210902.gz

如果它們尚不存在,我想將所有projectA*文件移動到創建子目錄的./projectA/所有文件。projectB*``./projectB/

日期之前的項目名稱各2021...不相同,需要從文件名中提取出來,但日期總是存在的,並且總是以202- 即 2021、2022 等開頭 - 我們不需要擔心 2029 之後會發生什麼: )

參數擴展可用於提取項目名稱,即子目錄名稱:

$ string=projectA20211103-23.gz
$ echo ${string%202*}
projectA

如何將其放入腳本中以針對目前目錄中的所有文件執行?應忽略文件夾和符號連結。

你的第一步很好。嘗試find在 bash shell 中使用和管道其結果,如下所示:

$ find . -maxdepth 1 -iname "project?202?????.gz" -print0 | xargs -0 -I {} bash -c '
       var="$1";
       var1="${var%%202*}";
       mkdir -p "$var1";
       echo mv "$var" "$var1"' xargs_bash {}

mv ./projectB20210901.gz ./projectB
mv ./projectA20210901.gz ./projectA
mv ./projectB20210902.gz ./projectB
mv ./projectA20210902.gz ./projectA

註釋:

  • 您可以將上面的一行寫在一行上。
  • 一旦您對輸出對應於mv您要發出的命令感到滿意,只需從一個行中刪除“echo”cmd 即可執行移動。
  • 我的目標不是簡潔;我喜歡可讀性。

這個怎麼運作:

  • find在目前目錄中查找並從那裡向下查找樹。
  • -maxdepth 1告訴 find 將其搜尋限制在目前目錄,即不要沿著樹向下搜尋。
  • -iname根據後面的模式以不區分大小寫的方式查找文件名
  • 文件名模式使用特殊字元: ?表示任意一個字元,*表示任意數量的字元
  • print0輸出結果在每個結果的末尾放置一個 \0 空字元,而不是標準的換行符。這是為了考慮到有時文件名包含換行符。
  • xargs -0在管道辨識出輸出中的每個文件名都由空字元與下一個文件名分隔之後
  • xargs bash -c '...' 生成一個 bash shell,其部分是根據find需要處理每個輸出,基於字元串操作,根據需要創建子目錄 ( mkdir -p),最後根據請求將每個文件移動到子目錄。

所以最後一個不帶cmd的單行echo程式碼是:

$ find . -maxdepth 1 -iname "project?202?????.gz" -print0 | xargs -0 -I {} bash -c 'var="$1"; var1="${var%%202*}"; mkdir -p "$var1"; mv "$var" "$var1"' xargs_bash {}

HTH。

引用自:https://unix.stackexchange.com/questions/676682