'{} \;' 是什麼意思在“查找”命令上下文中意味著什麼?

'{} \;' 是什麼意思在“查找”命令上下文中意味著什麼?

我想刪除具有size = 0.所以我嘗試:

find ./ -size 0 | xargs rm

但是,它對於名稱以空格開頭的檔案有問題。

在網路上搜尋我發現了這個:

find ./ -size 0 -exec rm -i {} \;

有用。但是,我認為我的使用方式xargs對此來說過於複雜。

這是什麼{} \;意思?

有人可以幫我解釋一下嗎?

我的英文不是很好,所以請使用簡單的寫作。

答案1

{}絕對沒有任何意義bash,因此在此處未經修改地作為參數傳遞給所執行的命令find

另一方面,;具有特定的含義bash。當順序命令位於同一命令行時,它通常用於分隔它們。這裡的反斜線 in\;精確地用於防止分號被解釋為命令分隔符,bash然後允許它作為參數傳遞給底層命令find。引用分號,即";"';',可能是使其不被處理的另一種方法。

命令:

find ./ -size 0 -exec rm -i {} \;

意思是:在當前目錄中查找(注意,/這裡沒有用,.無論如何都只能是一個目錄)任何大小為 0 的對象,對於找到的每個對象,運行命令rm -i name,即如果要刪除,則交互式提示每個文件它。{}被執行命令中找到的每個檔案名稱取代。一個很好的功能是,該檔案名稱嚴格來說是一個參數,無論檔案名稱是什麼(甚至包含嵌入的空格、製表符、換行符和任何字元)。xargs除非使用不可移植的 hack,否則情況不會如此。決賽;是為了結束該-exec條款。之所以需要對其終點進行界定,是因為其他find選項可能會跟隨該-exec選項,儘管這種情況很少這樣做。例如:

find . -name "*.js" -exec ls -l {} \; -name "special*" -exec wc -l {} \;

此命令的一個問題是它不會忽略非普通文件,因此可能會提示使用者刪除套接字、區塊和字元設備、管道和目錄。即使你回答“是”,後者總是會失敗。

另一個問題(雖然在這裡並不重要)是rm每個大小為零的檔案都會呼叫它。如果您替換-exec結尾 from/;+,將透過僅呼叫盡可能少的次數(通常只呼叫一次)來find優化子流程建立。rm

以下是我修改此命令的方法:

find . -type f -size 0 -exec rm -i {} +

答案2

使用 時find -exec{}會擴展到找到的每個結果。

例如,如果您有一個example包含 3 個檔案的目錄a.txtb.txt並且c.txt,find example/ -exec rm -i {} \;將擴展為:

find example/ -exec rm -i example/a.txt \;
find example/ -exec rm -i example/b.txt \;
find example/ -exec rm -i example/c.txt \;

\;末尾的 是簡單的轉義符,用於;指示 exec 模式的結束。否則,它會被 shell 本身解釋。

答案3

find命令的exec選項結合使用,該{}部分將替換為執行命令時找到的檔案的名稱。也很\;重要,因為它定義了正在執行的命令的結束

例如

find ~ -name \*.bak -exec -rm -f {} \;

將刪除.bak以使用者主目錄或其中包含的資料夾中任意位置結尾的所有檔案。透過執行rm -f找到的每個檔案。

xargs取得標準輸入行(通常來自管道),並在執行您給它的命令時從中形成參數的尾部部分

答案4

這是一個老問題,但我想添加更多資訊:

find ./ -size 0 -exec rm -i {} \;

在上一個指令中,\;是轉義分號。這會阻止 shell 處理該命令(即通常;會分隔命令)。

-exec參數將所有內容解釋為轉義分號之前的命令\;(即,rm -i {}它將是由 執行的內部命令find)。在內部命令中,{}代表參數擴展。在痛苦英語中,它的意思是「插入在這裡找到的檔案名稱」。

因此,如果找到的檔案是“file-a.txt”和“file-b.txt”,find則會執行rm -i file-a.txtthen rm -i file-b.txt

此命令的一個問題是它不會忽略非普通文件,因此可能會提示使用者刪除套接字、區塊和字元設備、管道和目錄。即使您回答“是”,後者也總是會失敗(即需要遞歸刪除目錄)

另一個問題(雖然在這裡並不重要)是rm每個大小為零的檔案都會呼叫它。如果您將-exec結尾替換為/;to , find 將透過僅呼叫盡可能少的次數(通常只呼叫一次)來+優化子流程建立。rm

以下是我修改此命令的方法:

find ./ -type f -size 0 -exec rm -i {} +

curly bracketsbraces:{}可以以不同的方式使用

支撐擴張

大括號可用於建構序列:

### prints out the numbers from 0 to 10
echo {0..10}

## prints out the same numbers, but in reverse order
echo {10..0}

## prints every second number, from 10 to 0
echo {10..0..2}

## prints every second letter, from z and working its way backwards to a.
echo {z..a..2}

我們也可以組合兩個或多個序列:

## prints out a pair of letters, from aa to zz.
echo {a..z}{a..z}

添加前綴和後綴:

### adds '"' as prefix and suffix
echo \"{These,words,are,quoted}\"
# output: "These" "words" "are" "quoted"

# concatenates the files file1, file2, and file3 into combined_file.
cat {file1,file2,file3} > combined_file

# copies "file22.txt" to "file22.backup"
cp file22.{txt,backup}

筆記:

大括號內不允許有空格,{...}除非空格是或者逃脫了

echo {file1,file2}\ :{\ A," B",' C'}
# output: file1 : A file1 : B file1 : C file2 : A file2 : B file2 : C

擴展支撐擴展。

大括號可用於建立數組。 Bash 中的陣列是透過將元素放在括號之間()並使用空格分隔每個元素來定義的,如下所示:

month=("Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec")

要存取數組中的元素,可以使用括號內的索引[]

 # Array indexes start at [0], so [3] points to the fourth item
$ echo ${month[3]}
## output: Apr

因此,我們可以建立一個類似這樣的陣列:

## builds an array that contains all the 2-letter combinations of the entire alphabet.
letter_combos=({a..z}{a..z})

## contains all the binary numbers for an 8-bit register, in ascending order,
## from 00000000, 00000001, 00000010, etc., to 11111111. 
dec2bin=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1})

最後一個特別有趣,因為 dec2bin 現在我們可以使用它來建立一個 8 位元十進位到二進位轉換器。假設您想知道 25 的二進制數是多少。你可以這樣做:

$ echo ${dec2bin[25]}
## output: 00011001

但是Teo有沒有更好的方法將十進制轉換為二進制?

  • 是的,有,但仍然很有趣,對吧?

分組命令

{ ... }可用於放置要在目前 shell 上下文中執行的命令清單。不子殼被建造。列表後面的分號;(或換行符號)是必需的

括號()用於在 a 中運行命令子殼:

menu_type=bar
echo $menu_type
## output: bar

## new lets called in a sub-shell
(menu_type=superbar; echo $menu_type)
## output: superbar

## back to the context
echo $menu_type
## output: bar

我們無法取得superbar的新值menu_type

但是,如果我們運行這樣的程式碼:

{ menu_type=superbar; echo $menu_type; }
## output: superbar

echo $menu_type
## output: superbar

{ ... }不會建立子 shell,這就是我們可以存取該menu_type值的原因。

{ ... }也稱為 an inline group,實際上,它創建了一個匿名函數(即沒有名稱的函數)。用簡單的英語來說,與「標準」函數不同,a 中的變數{ ... }對腳本的其餘部分仍然可見。

此外,{ ... }還可用於stdout將多個命令的輸出分組到其stdin.讓我們來看一個例子:

#!/bin/bash
# rpm-check.sh
#  Queries an rpm file for description, listing, and whether it can be installed.
#  Saves output to a file.

SUCCESS=0
E_NOARGS=65

if [ -z "$1" ]; then
  echo "Usage: `basename $0` rpm-file"
  exit $E_NOARGS
fi  

{ # Begin command group.
  echo
  echo "Archive Description:"
  rpm -qpi $1       # Query description.
  echo
  echo "Archive Listing:"
  rpm -qpl $1       # Query listing.
  echo
  rpm -i --test $1  # Query whether rpm file can be installed.
  if [ "$?" -eq $SUCCESS ]
  then
    echo "$1 can be installed."
  else
    echo "$1 cannot be installed."
  fi  
  echo              # End command group.
} > "$1.test"       # Redirects output of everything in block to file.

echo "Results of rpm test in file $1.test"

exit 0

現在,看看如何在群組中進行 I/O 重定向stdin

#!/bin/bash
File=/etc/fstab

## reads the first two lines of the file
{
  read line1
  read line2
} < $File

echo "First line in $File is:"
echo "$line1"
echo
echo "Second line in $File is:"
echo "$line2"

exit 0

將命令組的輸出儲存到檔案中的另一個範例

## exec commands sequentially and redirects the output of the ls command into the png-list.txt file
echo "I found all these png files:"; find . -iname "*.png"; echo "Within this bunch of files:"; ls > png-list.txt

## exec commands sequentially and redirects the output of the group into the png-list.txt file
{ echo "I found all these png files:"; find . -iname "*.png"; echo "Within this bunch of files:"; ls; } > png-list.txt

有什麼區別,特奧?

好吧,年輕學徒。第二個建立包含所有輸出的文件png-list.txt,從行 開始“I found all these png files:“,以命令輸出結束ls

子殼駭客

{ ... }Bash 為大括號組指令建立一個子 shell當且僅當它是管道的一部分,例如:

$ { A=1; { A=2; sleep 2; } ; echo $A; }
## output: 2

$ { A=1; { A=2; sleep 2; } | sleep 1; echo $A; }
## output: 1

筆記:

大括號和大括號內的指令清單之間有空格。這是因為{}是保留字(即內建在 shell 中的指令)。此外,命令清單必須以分號結尾;或使用換行符號分隔命令。

參數擴充

好吧,回到

month=("Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec")
echo ${month[3]}
## output: Apr

這裡的大括號{}不被用作序列建構器的一部分,而是作為產生參數擴展的一種方式。參數擴展涉及到盒子上的說明:

它採用大括號內的變數或表達式並將其擴展為它所代表的任何內容。

特奧這意味著什麼?

嗯,這意味著${...}告訴 shell 擴展其內部的所有內容。本例中,month就是我們先前定義的數組,即:

month=("Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec")

並且,3數組中的 item 指向"Apr"(即 Bash 中數組中的第一個索引是[0])。這意味著echo ${month[3]}擴展後會轉換為 echo "Apr"

將變數解釋為其值是擴展變數的一種方法,但我們也可以利用更多方法。我們可以使用參數擴展來操縱從變數中讀取的內容(即透過從末尾切掉一塊)。

假設你有一個像這樣的變數:

a="This sentence is too longgg"

## chops off the last two gs
echo ${a%gg}
## output: This sentence is too long

這對於將文件從一種格式轉換為另一種格式非常有用。例如,如果我們有一個命令,將名為 的 JPEG 影像image.jpg轉換為名為 的 PNG 映像image.png

convert image.jpg image.png

我們可以這樣重寫:

i='image.jpg'
## chops off the extension 'jpg' and adds 'png'
convert $i "${i%jpg}png"
## output: convert image.jpg image.png

但是 teo 這怎麼能比僅僅寫在檔案名稱中更有用呢?

好吧,當我們有一個包含數百張 JPEG 映像的目錄時,您需要轉換為 PNG,只需在其中執行以下命令:

for i in *.jpg; do convert $i ${i%jpg}png; done

....所有圖片都會自動轉換。歡迎您的年輕學徒。

如果您需要從變數的開頭截掉一個區塊,%請使用#

$ a="Hello World!"

## chops off the word 'Hello' and adds 'Goodbye'
$ echo Goodbye${a#Hello}
## output: Goodbye World!

文字佔位符

之後使用xargs -i(即替換字串選項)。雙{}大括號是輸出文字的佔位符。

## Execute 'echo ./<file>' for each file in the directory
ls . | xargs -i -t echo ./{} $1
#            ^^         ^^

路徑名

路徑名是包含完整路徑的檔案名稱。舉個例子,/home/<user>/Notes/todo.txt。這有時稱為絕對路徑。我們將在包含 的構造{}中遇到大部分情況。然而,這不是 shell 內建的。如果包含,則 find 會取代所選檔案的完整路徑名。find-exec <command> \;<command>{}"{}"

# Removes all core dump files from user's home directory.
find ~/ -name 'core*' -exec rm {} \;

相關內容