ฉันกำลังพยายามเขียนสคริปต์ที่จะทำงานในไดเรกทอรีที่กำหนดพร้อมกับไดเรกทอรีย่อยระดับเดียวหลายรายการ สคริปต์จะ cd ลงในแต่ละไดเรกทอรีย่อยดำเนินการคำสั่งในไฟล์ในไดเรกทอรีและ cd out เพื่อดำเนินการต่อไปยังไดเรกทอรีถัดไป วิธีที่ดีที่สุดในการทำเช่นนี้คืออะไร?
ฉันกำลังพยายามเขียนสคริปต์ที่จะทำงานในไดเรกทอรีที่กำหนดพร้อมกับไดเรกทอรีย่อยระดับเดียวหลายรายการ สคริปต์จะ cd ลงในแต่ละไดเรกทอรีย่อยดำเนินการคำสั่งในไฟล์ในไดเรกทอรีและ cd out เพื่อดำเนินการต่อไปยังไดเรกทอรีถัดไป วิธีที่ดีที่สุดในการทำเช่นนี้คืออะไร?
คำตอบ:
for d in ./*/ ; do (cd "$d" && somecommand); done
for d in ./*/
เริ่มห่วงว่าร้านค้าในทุกรายการ./*/
(รายชื่อของไฟล์ / โฟลเดอร์ในกรณีนี้) $d
ในตัวแปร do (cd "$d" && somecommand);
เริ่มเนื้อความของลูป ภายในร่างกายจะเริ่มsubshellและรันคำสั่งcd
และ somecommand
เนื่องจากมันเป็นเปลือกลูกเปลือกหลัก (เปลือกที่คุณใช้คำสั่งนี้) จะคงไว้ซึ่ง CWD และตัวแปรสภาพแวดล้อมอื่น ๆ done
เพียงแค่ปิดร่างกายห่วง
for d in ./*/ ; do (cd "$d" && ls); done
จะไม่ทำงาน แต่for d in ./*/ ; do (cd "$d" && for d in ./*/ ; do (cd "$d" && ls); done ); done
จะได้ผล - ใช้ ls เป็นคำสั่งในตัวอย่างนี้
-bash: cd: ./*/: No such file or directory
วิธีที่ดีที่สุดคือไม่ใช้cd
เลย:
find some/dir -type f -execdir somecommand {} \;
execdir
เป็นเหมือนexec
แต่ไดเรกทอรีทำงานแตกต่างกัน:
-execdir command {} [;|+]
Like -exec, but the specified command is run from the
subdirectory containing the matched file, which is not normally
the directory in which you started find. This a much more
secure method for invoking commands, as it avoids race
conditions during resolution of the paths to the matched files.
มันไม่ใช่ POSIX
find
ดำเนินการคำสั่งเหล่านั้นดังนั้นจึงไม่ทราบถึงนามแฝง ไดเรคทอรี่คืออะไรmd
และคือ.link
อะไร?
bash
: find . -type f -iname '*.link' -execdir ${BASH_ALIASES[md]} -i {} \;
คุณไม่จำเป็นต้องที่จะทำcat
ด้วยwget
ซึ่งมี-i
ธงสำหรับการอ่านใน URL จากไฟล์ นอกจากนี้ยังค่อนข้างแตกต่างจากคำถามเดิมของคุณ (เนื่องจากคุณสนใจเฉพาะไฟล์ที่มีชื่อ.link
และไม่ใช่ไฟล์อื่น ๆ ที่อาจมีอยู่)
cd -P .
for dir in ./*/
do cd -P "$dir" ||continue
printf %s\\n "$PWD" >&2
command && cd "$OLDPWD" ||
! break; done || ! cd - >&2
คำสั่งดังกล่าวไม่จำเป็นต้องทำ subshells ใด ๆ - มันเป็นเพียงแค่ติดตามความคืบหน้าในเปลือกปัจจุบันโดยสลับกันและ$OLDPWD
$PWD
เมื่อคุณcd -
เชลล์แลกเปลี่ยนค่าของตัวแปรทั้งสองนี้โดยทั่วไปมันจะเปลี่ยนไดเรกทอรี นอกจากนี้ยังพิมพ์ชื่อสำหรับแต่ละไดเรกทอรีตามที่ทำงานไปยัง stderr
ฉันเพิ่งดูครั้งที่สองและตัดสินใจว่าฉันจะทำงานได้ดีขึ้นด้วยการจัดการข้อผิดพลาด มันจะข้าม dir ที่มันไม่สามารถcd
- และcd
จะพิมพ์ข้อความเกี่ยวกับสาเหตุของ stderr - และมันจะbreak
มีรหัสทางออกที่ไม่เป็นศูนย์หากคุณcommand
ดำเนินการไม่สำเร็จหรือหากการรันcommand
มีผลต่อความสามารถในการกลับไปยังไดเรกทอรีต้นฉบับของคุณ $OLDPWD
- ในกรณีดังกล่าวมันจะใช้cd -
นามสกุล - และเขียนชื่อไดเรกทอรีการทำงานปัจจุบันที่เป็นผลลัพธ์ไปยัง stderr
for D in ./*; do
if [ -d "$D" ]; then
cd "$D"
run_something
cd ..
fi
done
youtube-dl
เลย