如何替換“$0”但保存舊值?

如何替換“$0”但保存舊值?

我試圖將所有以“m”開頭的檔案重命名為相同的名稱,除了第一個字元(或本例中的“m”)被刪除。

我的策略是:

  1. 列出所有文件,其中ls
  2. 過濾出我想要的,egrep
  3. 在我想要的字串旁邊產生我不想要的字串,用空格分隔,awk例如,mfoo foo
  4. 送入xargsmv mfoo foo

一些問題:

  • 這是一個好的策略嗎?
  • 什麼是更好的?

我陷入了第三步,以下是我解決這個問題的方法。

我正在以下目錄中工作:

$ find .
.
./cat
./mbar
./mbaz
./mfoo

我能夠快速得到 1-2:

$ ls | egrep '^m'
mbar
mbaz
mfoo

第3步比較困難。我曾經gsub生成我想要的第二個字串,但我不確定如何「將其與用空格分隔的原始值黏在一起」:

$ ls | egrep '^m' | awk '{ gsub(/^./, ""); print }'
bar
baz
foo

步驟 4 對我來說很有意義,儘管我不確定如何完成第 3 步,所以我還無法完成它。以下是我認為它應該如何運作的一個例子:

$ echo mfoo foo | xargs mv
$ find .
.
./cat
./foo
./mbar
./mbaz

我想我已經很接近了,我只需要找出如何保存舊值並將其列印在 gsubed 值旁邊。我嘗試過以下小示例,但它不起作用:

$ echo mfoo | awk '
pipe quote> { old = $0 }
pipe quote> { new = gsub(/^./, "") }
pipe quote> { print $old " " $new }'
awk: illegal field $(mfoo), name "old"
 input record number 1, file
 source line number 4
  • 如何替換$0但保存舊值?
  • 為什麼我會收到此錯誤?

答案1

這應該要處理整個操作:

for file in m*; do mv "${file}" "${file#m}"; done

在運行之前,請先檢查一下

for file in m*; do echo mv "${file}" "${file#m}"; done

這將m*glob 用於步驟 1 和 2,然後${file#m}(從 的開頭刪除“m” ${file})用於步驟 3,最後使用循環用於步驟 4。

要回答您的 AWK 問題,您可以這樣解決:

echo mfoo | awk '{ print $0, substr($0, 2) }'

AWK 變數不使用$,僅適用於欄位;這就是您的錯誤的來源:AWK 將其理解$old為「根據 的​​值編號的欄位的值old」。如果將命令放在一個區塊中(假設它們具有相同的模式),那麼也更容易閱讀。修復你的腳本給出

echo mfoo | awk '{ old = $0; gsub(/^./, ""); print old, $0 }'

答案2

ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); $0 = x " " $0 }1' | xargs -l -t mv

Posix-實現是透過以下-L選項xargs

ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); $0 = x " " $0 }1' | xargs -L 1 -t mv

ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); print x, $0 }' | xargs -L 1 -t mv

基於什麼我回答對於您之前關於 的詢問xargs,我們可以在這個例子中充分利用所學到的知識。

我稍微修改了你的awk程式碼:它保留了原始行($0),因為gsubfunc 會破壞它。然後,我們將舊的和新的放在一起,以獲得我們想要發送到的行xargs,然後mv使用正確的參數呼叫以實現重命名。

答案3

更好的策略是使用rename命令。

請注意,此命令的確切語法是特定於發行版的,請參閱man您的特定發行版版本的頁面。例如,在 Ubuntu 上,它具有 Perl 實現rename,您可以使用正規表示式:

rename -nono 's/^m//' m*

注意:刪除該-nono標誌才能實際執行重新命名。

相關內容