การใช้รายการชื่อไฟล์ที่สร้างขึ้นเป็นรายการอาร์กิวเมนต์ - พร้อมช่องว่าง


16

findฉันพยายามที่จะเรียกใช้สคริปต์กับรายการของชื่อไฟล์ที่เก็บรวบรวมโดย ไม่มีอะไรพิเศษเพียง someting เช่นนี้:

$ myscript `find . -name something.txt`

ปัญหาคือชื่อพา ธ บางส่วนมีช่องว่างดังนั้นพวกเขาจึงแยกออกเป็นชื่อที่ไม่ถูกต้องสองชื่อในการขยายอาร์กิวเมนต์ ปกติฉันจะล้อมรอบชื่อด้วยเครื่องหมายคำพูด แต่ที่นี่พวกเขาแทรกโดยการขยาย backquote ฉันพยายามกรองเอาท์พุทของfindและรอบ ๆ ชื่อไฟล์แต่ละรายการด้วยเครื่องหมายคำพูด แต่เมื่อถึงเวลาที่เห็นพวกเขามันสายเกินไปที่จะดึงออกมาและพวกเขาจะถือว่าเป็นส่วนหนึ่งของชื่อไฟล์:

$ myscript `find . -name something.txt | sed 's/.*/"&"/'`
No such file or directory: '"./somedir/something.txt"'

ใช่นั่นเป็นกฎสำหรับวิธีการประมวลผลบรรทัดคำสั่ง แต่ฉันจะแก้ไขได้อย่างไร

นี่เป็นเรื่องที่น่าอาย แต่ฉันไม่สามารถหาวิธีที่เหมาะสมได้ ในที่สุดฉันก็รู้ว่าจะทำอย่างไรกับxargs -0 -n 10000... แต่มันเป็นแฮ็คที่น่าเกลียดที่ฉันยังต้องการถาม: ฉันจะอ้างถึงผลลัพธ์ของการขยาย backquote หรือบรรลุผลแบบเดียวกันได้อย่างไร?

แก้ไข:ฉันสับสนเกี่ยวกับความจริงที่ว่าxargs ไม่เก็บขัดแย้งทั้งหมดเป็นรายการอาร์กิวเมนต์เดียวเว้นแต่จะบอกเป็นอย่างอื่นหรือข้อ จำกัด ของระบบอาจจะเกิน ขอบคุณทุกคนที่ทำให้ฉันตรง! คนอื่นจำไว้ว่าเมื่อคุณอ่านคำตอบที่ยอมรับเพราะมันไม่ได้ชี้ให้เห็นโดยตรง

ฉันยอมรับคำตอบแล้ว แต่คำถามของฉันยังคงอยู่: ไม่มีวิธีใดในการป้องกันช่องว่างใน$(...)การขยายย้อนหลัง (หรือ)? (โปรดทราบว่าโซลูชันที่ยอมรับนั้นเป็นคำตอบที่ไม่ใช่การทุบตี)


ฉันเดาว่าคุณต้องเปลี่ยนสิ่งที่เชลล์ใช้เป็นตัวคั่นชื่อไฟล์ (ตัวอย่างเช่นโดยการเล่นด้วยค่าของ IFS วิธีหนึ่งที่เป็นไปได้คือIFS="ขึ้นบรรทัดใหม่") แต่จำเป็นต้องเรียกใช้สคริปต์เหนือชื่อไฟล์ทั้งหมดหรือไม่ หากไม่ใช่ให้ลองใช้ค้นหาตัวเองเพื่อรันสคริปต์สำหรับแต่ละไฟล์
njsg

การเปลี่ยน IFS เป็นความคิดที่ดีไม่เคยคิดเลย! ไม่ใช่ประโยชน์สำหรับการใช้ commandline แต่ยัง :-) และใช่เป้าหมายคือการส่งผ่านข้อโต้แย้งทั้งหมดไปยังการภาวนาของสคริปต์ของฉัน
alexis

คำตอบ:


12

คุณสามารถทำสิ่งต่อไปนี้โดยใช้การใช้งานบางอย่างfindและxargsเช่นนี้

$ find . -type f -print0 | xargs -r0 ./myscript

หรือมาตรฐานเพียงfind:

$ find . -type f -exec ./myscript {} +

ตัวอย่าง

ว่าฉันมีไดเรกทอรีตัวอย่างต่อไปนี้

$ tree
.
|-- dir1
|   `-- a\ file1.txt
|-- dir2
|   `-- a\ file2.txt
|-- dir3
|   `-- a\ file3.txt
`-- myscript

3 directories, 4 files

./myscriptตอนนี้ขอบอกว่าผมมีนี้

#!/bin/bash

for i in "$@"; do
    echo "file: $i"
done

ตอนนี้เมื่อฉันเรียกใช้คำสั่งต่อไปนี้

$ find . -type f -print0 | xargs -r0 ./myscript 
file: ./dir2/a file2.txt
file: ./dir3/a file3.txt
file: ./dir1/a file1.txt
file: ./myscript

หรือเมื่อฉันใช้แบบฟอร์มที่ 2 เช่นนั้น:

$ find . -type f -exec ./myscript {} +
file: ./dir2/a file2.txt
file: ./dir3/a file3.txt
file: ./dir1/a file1.txt
file: ./myscript

รายละเอียด

ค้นหา + xargs

ทั้งสองวิธีที่กล่าวมาข้างต้นนั้นดูแตกต่างกัน แรกคือการเอาท์พุทจากการค้นหาแยกโดยใช้ NULL ( \0) ผ่าน-print0สวิตช์เพื่อค้นหา xargs -0ถูกออกแบบมาเพื่อใช้การป้อนข้อมูลว่าแยกโดยใช้ NULLs ไวยากรณ์ที่ไม่เป็นมาตรฐานนั้นได้รับการแนะนำโดย GNU findและxargsยังพบได้ในทุกวันนี้ในบางส่วนเช่น BSD ล่าสุด -rตัวเลือกที่จะต้องหลีกเลี่ยงการโทรmyscriptถ้าfindพบอะไรกับ GNUfindแต่ไม่ได้มี BSDs

หมายเหตุ:วิธีการทั้งหมดนี้ขึ้นอยู่กับความจริงที่ว่าคุณจะไม่ผ่านสายที่ยาวเกินไป ถ้าเป็นเช่นนั้นการอุทธรณ์ครั้งที่ 2 ของ./myscriptจะถูกเตะออกพร้อมกับส่วนที่เหลือของผลการค้นหาที่ตามมา

ค้นหาด้วย +

นั่นเป็นวิธีมาตรฐาน (แม้ว่าจะถูกเพิ่มเข้ามาค่อนข้างเร็ว ๆ นี้ (2005) ในการนำ GNU ไปใช้find) ความสามารถในการทำในสิ่งที่เรากำลังทำอยู่กับที่ถูกสร้างขึ้นตามตัวอักษรลงในxargs findดังนั้นfindจะหารายชื่อไฟล์แล้วส่งรายการนั้นให้มากที่สุดเท่าที่จะเป็นไปตามคำสั่งที่ระบุไว้หลังจากนั้น-exec (โปรดทราบว่า{}จะต้องเป็นครั้งสุดท้ายก่อน+นี้ในกรณีนี้) เรียกใช้คำสั่งหลายครั้งหากจำเป็น

ทำไมไม่มีข้อความ

ในตัวอย่างแรกเรากำลังใช้ช็อตคัทโดยหลีกเลี่ยงปัญหาที่เกิดขึ้นกับข้อความโดยใช้ NULL เพื่อแยกอาร์กิวเมนต์ เมื่อไหร่xargsได้รับรายการนี้จะมีคำสั่งให้แยก NULL อย่างมีประสิทธิภาพปกป้องอะตอมคำสั่งของเราแต่ละคน

ในตัวอย่างที่สองเราเก็บผลลัพธ์ไว้ภายใน findและเพื่อให้มันรู้ว่าแต่ละอะตอมไฟล์คืออะไรและจะรับประกันว่าจะจัดการได้อย่างเหมาะสมดังนั้นจึงหลีกเลี่ยงธุรกิจ whoie ที่อ้างถึงพวกเขา

ขนาดสูงสุดของบรรทัดคำสั่ง?

คำถามนี้เกิดขึ้นเป็นครั้งคราวเพื่อเป็นโบนัสที่ฉันเพิ่มลงในคำตอบนี้ส่วนใหญ่ฉันจะพบได้ในอนาคต คุณสามารถใช้xargsเพื่อดูว่าขีด จำกัด ของสภาพแวดล้อมเป็นอย่างไร:

$ xargs --show-limits
Your environment variables take up 4791 bytes
POSIX upper limit on argument length (this system): 2090313
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2085522
Size of command buffer we are actually using: 131072

1
ขอบคุณ แต่ผมต้องผ่านการขัดแย้งทั้งหมดไปยังเดียวกันอุทธรณ์ของสคริปต์ของฉัน นั่นเป็นคำอธิบายปัญหา แต่ฉันคิดว่าฉันไม่ได้อธิบายอย่างชัดเจนว่าไม่ใช่เรื่องบังเอิญ
อเล็กซิส

@alexis - อ่านคำตอบอีกครั้งพวกเขาจะส่งข้อโต้แย้งทั้งหมดไปยังการเรียกใช้สคริปต์ของคุณเพียงครั้งเดียว
slm

ฉันจะสาปแช่ง! ฉันไม่รู้เกี่ยวกับการ+โต้เถียงfind(และคุณใช้งาน+ในร้อยแก้วด้วยดังนั้นฉันพลาดคำอธิบายของคุณในครั้งแรก) แต่ยิ่งกว่านั้นฉันก็เข้าใจผิดว่าอะไรเป็นxargsค่าเริ่มต้น !!! ในสามทศวรรษของการใช้ระบบปฏิบัติการยูนิกซ์ฉันไม่เคยมีการใช้งานสำหรับมันจนถึงขณะนี้ แต่ฉันคิดว่าฉันรู้กล่องเครื่องมือของฉัน ...
อเล็กซิส

@alexis - ฉันคิดว่าคุณจะพลาดสิ่งที่เราพูด ใช่xargsเป็นปีศาจของคำสั่ง คุณต้องอ่านมันและfindทำหน้าคนหลายครั้งเพื่อห้อมล้อมสิ่งที่พวกเขาสามารถทำได้ เดือนพฤษภาคมของสวิทช์เป็นสิ่งที่ตรงกันข้ามของกันและกันเพื่อเพิ่มความสับสน
slm

@alexis - ยังมีอีกหนึ่งสิ่งที่จะเพิ่มลงในกล่องเครื่องมืออย่าใช้ backquotes / backticks สำหรับการเรียกใช้คำสั่งที่ซ้อนกันใช้$(..)ทันทีแทน มันจัดการโดยอัตโนมัติจากการทำรังของคำพูด ฯลฯ Backticks จะถูกคัดค้าน
slm

3
find . -name something.txt -exec myscript {} +

ในข้างต้นพบว่าทั้งหมดชื่อไฟล์ที่ตรงกันและให้พวกเขาเป็นข้อโต้แย้งที่จะfind myscriptใช้ได้กับชื่อไฟล์ไม่ว่าจะมีช่องว่างหรืออักขระแปลก ๆ

หากชื่อไฟล์ทั้งหมดพอดีกับหนึ่งบรรทัด myscript จะถูกดำเนินการหนึ่งครั้ง หากรายการนั้นยาวเกินกว่าที่เชลล์จะจัดการได้แล้ว find จะรัน myscript หลาย ๆ ครั้งตามต้องการ

เพิ่มเติม:มีกี่ไฟล์ที่พอดีกับบรรทัดคำสั่ง? man findบอกว่าfindbuilds มันบรรทัดคำสั่ง "มากแบบเดียวกับที่ xargs สร้างมัน" และman xargsว่าข้อ จำกัด xargs --show-limitsที่มีระบบและขึ้นอยู่กับว่าคุณสามารถตรวจสอบได้โดยการทำงาน ( getconf ARG_MAXก็เป็นไปได้เช่นกัน) บน Linux โดยทั่วไปขีด จำกัด(แต่ไม่เสมอไป)ประมาณ 2 ล้านตัวอักษรต่อบรรทัดคำสั่ง


2

อีกสองสามคำตอบที่ดีของ @ slm

ข้อ จำกัด เกี่ยวกับขนาดของอาร์กิวเมนต์อยู่ในการexecve(2)เรียกระบบ (จริง ๆ แล้วมันมีขนาดสะสมของอาร์กิวเมนต์และสตริงสภาพแวดล้อมและพอยน์เตอร์) หากmyscriptเขียนด้วยภาษาที่เชลล์ของคุณสามารถตีความได้บางทีคุณอาจไม่จำเป็นต้องเรียกใช้งานคุณสามารถให้เชลล์ของคุณตีความได้โดยไม่ต้องใช้ล่ามอีก

หากคุณเรียกใช้สคริปต์เป็น:

(. myscript x y)

มันเหมือนกับ:

myscript x y

ยกเว้นว่ามันจะถูกตีความโดยลูกของเปลือกปัจจุบันแทนที่จะรันมัน (ซึ่งในที่สุดเกี่ยวข้องกับการดำเนินการ sh (หรือสิ่งที่ระบุบรรทัดเธอปังถ้ามี) ที่มีการขัดแย้งมากยิ่งขึ้น)

ตอนนี้เห็นได้ชัดว่าคุณไม่สามารถใช้find -exec {} +กับ.คำสั่งตามที่เป็นคำสั่งในตัวของเปลือกก็จะต้องมีการดำเนินการโดยเปลือกไม่ได้โดย.find

ด้วยzshมันง่าย:

IFS=$'\0'
(. myscript $(find ... -print0))

หรือ:

(. myscript ${(ps:\0:)"$(find ... -print0)"}

ถึงแม้ว่าzshคุณจะไม่ต้องการfindตั้งแต่แรกเพราะคุณสมบัติส่วนใหญ่ของมันถูกสร้างขึ้นเพื่อให้zshกลมกลืน

bashอย่างไรก็ตามตัวแปรไม่สามารถมีอักขระ NUL ได้ดังนั้นคุณต้องหาวิธีอื่น วิธีหนึ่งอาจเป็น:

files=()
while IFS= read -rd '' -u3 file; do
  files+=("$file")
done 3< <(find ... -print0)
(. myscript "${files[@]}")

คุณอาจใช้การวนซ้ำแบบ zsh-style ซ้ำพร้อมกับglobstarตัวเลือกในbash4.0 และใหม่กว่า:

shopt -s globstar failglob dotglob
(. myscript ./**/something.txt)

โปรดทราบว่า**ติดตาม symlink ไปยังไดเรกทอรีจนกว่าจะได้รับการแก้ไขในbash4.3 นอกจากนี้โปรดทราบbashว่าไม่ได้ใช้ตัวระบุแบบzshกลม ๆ ดังนั้นคุณจะไม่ได้รับคุณสมบัติทั้งหมดของที่findนั่น

อีกทางเลือกหนึ่งคือใช้ GNU ls:

eval "files=(find ... -exec ls -d --quoting-style=shell-always {} +)"
(. myscript "${files[@]}")

นอกจากนี้ยังสามารถใช้วิธีการข้างต้นได้หากคุณต้องการให้แน่ใจว่าmyscriptจะดำเนินการเพียงครั้งเดียว (ล้มเหลวหากรายการอาร์กิวเมนต์มีขนาดใหญ่เกินไป) บน Linux เวอร์ชันล่าสุดคุณสามารถเพิ่มและยกข้อ จำกัด นั้นในรายการอาร์กิวเมนต์ด้วย:

ulimit -s 1048576

(ขนาดสแต็ค 1GiB หนึ่งในสี่สามารถใช้กับรายการ arg + env)

ulimit -s unlimited

(ไม่มีขีด จำกัด)


1

ในระบบส่วนใหญ่มีข้อ จำกัด เกี่ยวกับความยาวของ commandline ผ่านโปรแกรมใด ๆ ที่ใช้หรือxargs -exec command {} +จากman find:

-exec command {} +
      This  variant  of the -exec action runs the specified command on
      the selected files, but the command line is built  by  appending
      each  selected file name at the end; the total number of invoca
      tions of the command will  be  much  less  than  the  number  of
      matched  files.   The command line is built in much the same way
      that xargs builds its command lines.  Only one instance of  `{}'
      is  allowed  within the command.  The command is executed in the
      starting directory.

การร้องขอจะน้อยกว่ามาก แต่ไม่รับประกันว่าจะเป็นหนึ่ง สิ่งที่คุณควรทำคือการอ่าน NUL แยกชื่อไฟล์ในสคริปต์จาก stdin -o -เป็นไปได้ขึ้นอยู่กับอาร์กิวเมนต์ ฉันจะทำสิ่งที่ชอบ:

$ find . -name something.txt -print0 | myscript -0 -o -

และใช้อาร์กิวเมนต์ตัวเลือกเพื่อให้myscriptสอดคล้อง


ใช่ระบบปฏิบัติการกำหนดข้อ จำกัด ในจำนวน / ขนาดของอาร์กิวเมนต์ที่สามารถส่งผ่านได้ บนระบบ Linux ที่ทันสมัยนี่คือ (ขนาดยักษ์) ( linux.die.net/man/2/execve ) (1/4 ของขนาดสแต็กอาร์กิวเมนต์ 0x7FFFFFFF) AFAIK ทุบตีตัวเองไม่ได้กำหนดขีด จำกัด ใด ๆ รายการของฉันมีขนาดเล็กกว่ามากและปัญหาของฉันเกิดจากความเข้าใจผิดหรือการจำผิดวิธีการxargsทำงาน วิธีแก้ปัญหาของคุณนั้นแข็งแกร่งที่สุด แต่ในกรณีนี้มันมีราคาแพงเกินไป
อเล็กซิส

0

ไม่มีวิธีใดในการป้องกันช่องว่างในการขยาย backtick (หรือ $ (... )) ใช่ไหม

ไม่ไม่มี ทำไมถึงเป็นอย่างนั้น?

Bash ไม่มีทางรู้ว่าควรจะป้องกันอะไรและอะไรไม่ควร

ไม่มีอาร์เรย์ในไฟล์ / ไพพ์ยูนิกซ์ มันเป็นแค่กระแสไบต์ คำสั่งภายใน``หรือ$()ส่งออกกระแสซึ่งทุบตีกลืนและถือว่าเป็นสายเดียว เมื่อถึงจุดนี้คุณมีสองทางเลือกเท่านั้น: ใส่ไว้ในเครื่องหมายอัญประกาศเพื่อให้เป็นสตริงเดียวหรือวางไว้เปล่า ๆ เพื่อให้ทุบตีมันแยกตามพฤติกรรมที่กำหนดไว้

ดังนั้นสิ่งที่คุณต้องทำถ้าคุณต้องการอาเรย์คือการกำหนดรูปแบบไบต์ที่มีอาเรย์และนั่นคือสิ่งที่เครื่องมือชอบxargsและfindทำ: ถ้าคุณเรียกใช้พวกเขาด้วย-0โต้แย้งพวกเขาทำงานตามรูปแบบอาเรย์ไบนารีที่สิ้นสุดองค์ประกอบ null null เพิ่ม semantics ให้กับ stream ไบต์ทึบแสง

น่าเสียดายที่bashไม่สามารถกำหนดค่าให้แยกสตริงบนไบต์ที่ว่างได้ ขอบคุณ/unix//a/110108/17980สำหรับแสดงให้เราเห็นว่าzshสามารถทำได้

xargs

คุณต้องการให้คำสั่งรันครั้งเดียวและคุณบอกว่าวิธีxargs -0 -n 10000แก้ปัญหาของคุณ ไม่รับประกันว่าหากคุณมีพารามิเตอร์มากกว่า 10,000 พารามิเตอร์คำสั่งของคุณจะทำงานมากกว่าหนึ่งครั้ง

ถ้าคุณต้องการทำให้มันรันอย่างเคร่งครัดหนึ่งครั้งหรือล้มเหลวคุณต้องระบุ-xอาร์กิวเมนต์และ-nอาร์กิวเมนต์ที่มีขนาดใหญ่กว่า-sอาร์กิวเมนต์ (จริง ๆ : ใหญ่พอที่ทั้งกลุ่มของอาร์กิวเมนต์ที่มีความยาวเป็นศูนย์รวมกับชื่อของคำสั่งจะไม่พอดี-sขนาด) ( man xargsดูข้อความที่ตัดตอนมาด้านล่าง)

ระบบที่ฉันใช้อยู่ในปัจจุบันมีสแต็ก จำกัด ประมาณ 8M ดังนั้นนี่คือขีด จำกัด ของฉัน:

$ printf '%s\0' -- {1..1302582} | xargs -x0n 2076858 -s 2076858 /bin/true
xargs: argument list too long
$ printf '%s\0' -- {1..1302581} | xargs -x0n 2076858 -s 2076858 /bin/true
(no output)

ทุบตี

หากคุณไม่ต้องการมีส่วนร่วมกับคำสั่งภายนอกวงวนการอ่านขณะป้อนอาร์เรย์ดังที่แสดงไว้ใน/unix//a/110108/17980เป็นวิธีเดียวในการทุบตีเพื่อแบ่งสิ่ง ไบต์ว่าง

แนวคิดในการจัดหาสคริปต์( . ... "$@" )เพื่อหลีกเลี่ยงข้อ จำกัด ขนาดสแต็กต์นั้นยอดเยี่ยม (ฉันลองใช้งานได้!) แต่อาจไม่สำคัญสำหรับสถานการณ์ปกติ

การใช้ fd พิเศษสำหรับไปป์กระบวนการนั้นมีความสำคัญหากคุณต้องการอ่านอย่างอื่นจาก stdin แต่ไม่เช่นนั้นคุณจะไม่ต้องการมัน

ดังนั้นวิธี "ดั้งเดิม" ที่ง่ายที่สุดสำหรับความต้องการของใช้ในครัวเรือนประจำวัน:

files=()
while IFS= read -rd '' file; do
    files+=("$file")
done <(find ... -print0)

myscriptornonscript "${files[@]}"

ถ้าคุณชอบทรีโปรเซสของคุณที่สะอาดและน่าดูเมธอดนี้อนุญาตให้คุณทำexec mynonscript "${files[@]}"ซึ่งจะลบกระบวนการ bash ออกจากหน่วยความจำแทนที่ด้วยคำสั่งที่เรียกว่า xargsจะยังคงอยู่ในหน่วยความจำเสมอในขณะที่คำสั่งที่เรียกใช้ทำงานแม้ว่าคำสั่งนั้นจะทำงานเพียงครั้งเดียว


สิ่งที่พูดกับวิธีทุบตีพื้นเมืองคือ:

$ time { printf '%s\0' -- {1..1302581} | xargs -x0n 2076858 -s 2076858 /bin/true; }

real    0m2.014s
user    0m2.008s
sys     0m0.172s

$ time {
  args=()
  while IFS= read -rd '' arg; do
    args+=( "$arg" )
  done < <(printf '%s\0' -- $(echo {1..1302581}))
  /bin/true "${args[@]}"
}
bash: /bin/true: Argument list too long

real    107m51.876s
user    107m38.532s
sys     0m7.940s

bash ไม่เหมาะสำหรับการจัดการอาเรย์


ผู้ชาย xargs :

-n max-args

ใช้อาร์กิวเมนต์ max-args มากที่สุดต่อบรรทัดคำสั่ง อาร์กิวเมนต์น้อยกว่า max-args จะถูกใช้หากเกินขนาด (ดูตัวเลือก -s) ยกเว้นว่ามีการกำหนดตัวเลือก -x ซึ่ง xargs จะออกจากกรณีนี้

-s max-chars

ใช้อักขระสูงสุด max-chars ต่อบรรทัดคำสั่งรวมถึงคำสั่งและอาร์กิวเมนต์เริ่มต้นและการยกเลิก nulls ที่ส่วนท้ายของสตริงอาร์กิวเมนต์ ค่าสูงสุดที่อนุญาตนั้นขึ้นอยู่กับระบบและคำนวณเป็นข้อจำกัดความยาวอาร์กิวเมนต์สำหรับ exec น้อยกว่าขนาดของสภาพแวดล้อมของคุณน้อยกว่า 2048 ไบต์ของ headroom หากค่านี้มากกว่า 128KiB จะใช้ 128Kib เป็นค่าเริ่มต้น มิฉะนั้นค่าเริ่มต้นคือสูงสุด 1KiB คือ 1024 ไบต์

-x

ออกหากขนาด (ดูตัวเลือก -s) เกิน


ขอบคุณสำหรับปัญหาทั้งหมด แต่หลักฐานพื้นฐานของคุณไม่สนใจข้อเท็จจริงที่ว่าทุบตีตามปกติจะใช้ระบบการประมวลผลการเสนอราคาที่ซับซ้อน แต่ไม่ใช่ในการขยาย backquote เปรียบเทียบดังต่อไปนี้ (ซึ่งทั้งสองข้อผิดพลาดให้ แต่แสดงให้เห็นความแตกต่าง): เมื่อเทียบกับls "what is this" ls `echo '"what is this"'` มีคนละเลยที่จะใช้การประมวลผลการเสนอราคาสำหรับผลลัพธ์ของ backquotes
alexis

ฉันดีใจที่ backquotes ไม่ประมวลผลการเสนอราคา ความจริงที่ว่าพวกเขาแยกคำได้ทำให้เกิดลักษณะสับสนพอรอยขีดข่วนและข้อบกพร่องด้านความปลอดภัยในประวัติศาสตร์คอมพิวเตอร์ที่ทันสมัย
clacke

คำถามคือ "ไม่มีวิธีใดที่จะป้องกันช่องว่างใน$(...)การขยายแบ็คทิก (หรือ)?" ดังนั้นจึงเหมาะสมที่จะไม่สนใจการประมวลผลที่ไม่ได้ทำในสถานการณ์นั้น
clacke

รูปแบบอาร์เรย์องค์ประกอบที่สิ้นสุดด้วยค่า null เป็นวิธีที่ง่ายที่สุดและปลอดภัยที่สุดในการแสดงอาร์เรย์ มันเป็นเพียงความอัปยศที่bashไม่สนับสนุนกำเนิดเช่นเห็นได้ชัดว่าzshไม่
clacke

ในความเป็นจริงเพียงแค่สัปดาห์นี้ฉันใช้printf "%s\0"และxargs -0กำหนดเส้นทางรอบสถานการณ์การอ้างอิงซึ่งเครื่องมือระดับกลางจะผ่านพารามิเตอร์ผ่านสตริงที่แยกวิเคราะห์โดยเชลล์ การอ้างกลับมากัดคุณอยู่เสมอ
clacke
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.