ฉันกำลังพยายามเขียนสคริปต์ที่จะทำงานในไดเรกทอรีที่กำหนดพร้อมกับไดเรกทอรีย่อยระดับเดียวหลายรายการ สคริปต์จะ 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เลย