เหตุใดจึงจำเป็น xargs


25

สมมติว่าฉันต้องการลบไฟล์ทั้งหมดในไดเรกทอรียกเว้นไฟล์ที่มีชื่อว่า "notes.txt" ฉันจะทำเช่นนี้กับไปป์ไลน์, ls | grep -v "notes.txt" | xargs rm. เหตุใดฉันจึงต้องการ xargs หากเอาต์พุตของไพพ์ที่สองคืออินพุตที่ rm ควรใช้?

เพื่อประโยชน์ในการเปรียบเทียบไปป์ไลน์echo "#include <knowledge.h>" | cat > foo.cแทรกข้อความ echoed ลงในไฟล์โดยไม่ต้องใช้ xargs ท่อสองท่อนี้แตกต่างกันอย่างไร?


3
คุณไม่ควรใช้ls | grep -v "notes.txt" | xargs rmในการลบทุกอย่างยกเว้นnotes.txtหรือโดยทั่วไปไม่เคยแยกlsเอาท์พุท คำสั่งของคุณจะแตกถ้าไฟล์เดียวมีช่องว่างตัวอย่างเช่น วิธีที่ปลอดภัยมากขึ้นจะเป็นrm !(notes.txt)ในทุบตี (กับshopt -s extglobชุด) หรือrm ^notes.txtใน zsh (มีEXTENDED_GLOB) เป็นต้น
slhck

เพื่อหลีกเลี่ยงช่องว่างที่คุณสามารถทำได้find . -maxdepth 1 -mindepth 1 -print0 | xargs -0แทนls | xargs:-)
flob

คำตอบ:


35

คุณกำลังสับสนกับอินพุตที่แตกต่างกันสองประเภท: STDIN และอาร์กิวเมนต์ อาร์กิวเมนต์คือรายการของสตริงที่จัดเตรียมให้กับคำสั่งในขณะที่เริ่มต้นโดยปกติแล้วจะระบุไว้หลังจากชื่อคำสั่ง (เช่นecho these are some argumentsหรือrm file1 file2) ในทางกลับกัน STDIN เป็นกระแสข้อมูลของไบต์ (บางครั้งข้อความบางครั้งไม่) ที่คำสั่งสามารถ (เป็นทางเลือก) อ่านหลังจากเริ่มต้น นี่คือตัวอย่างบางส่วน (โปรดทราบว่าcatสามารถรับอาร์กิวเมนต์หรือ STDIN ได้ แต่ทำสิ่งต่าง ๆ กับมัน)

echo file1 file2 | cat    # Prints "file1 file2", since that's the stream of
                          # bytes that echo passed to cat's STDIN
cat file1 file2    # Prints the CONTENTS of file1 and file2
echo file1 file2 | rm    # Prints an error message, since rm expects arguments
                         # and doesn't read from STDIN

xargs สามารถคิดเป็นการแปลงอินพุตสไตล์ STDIN เป็นอาร์กิวเมนต์:

echo file1 file2 | cat    # Prints "file1 file2"
echo file1 file2 | xargs cat    # Prints the CONTENTS of file1 and file2

echo จริงๆแล้วจะตรงกันข้ามกันมากขึ้นหรือน้อยลง: มันแปลงอาร์กิวเมนต์เป็น STDOUT (ซึ่งสามารถถูกไพพ์ไปยัง STDIN ของคำสั่งอื่น ๆ ):

echo file1 file2 | echo    # Prints a blank line, since echo doesn't read from STDIN
echo file1 file2 | xargs echo    # Prints "file1 file2" -- the first echo turns
                                 # them from arguments into STDOUT, xargs turns
                                 # them back into arguments, and the second echo
                                 # turns them back into STDOUT
echo file1 file2 | xargs echo | xargs echo | xargs echo | xargs echo    # Similar,
                                 # except that it converts back and forth between
                                 # args and STDOUT several times before finally
                                 # printing "file1 file2" to STDOUT.

9

catใช้อินพุตจากSTDINและrmไม่ สำหรับคำสั่งดังกล่าวคุณจะต้องวนxargsซ้ำทีSTDINละบรรทัดและดำเนินการคำสั่งด้วยพารามิเตอร์บรรทัดคำสั่ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.