สำรวจไดเรกทอรีย่อยทั้งหมดในและทำบางสิ่งใน Unix shell script


17

ฉันต้องการเชลล์สคริปต์ของฉันเพื่อเยี่ยมชมไดเรกทอรีย่อยทั้งหมดในไดเรกทอรีหลัก ทำบางสิ่งในไดเรกทอรีส่งออกไปยังไฟล์สปูลและย้ายไปยังไดเรกทอรีถัดไป พิจารณา Dir หลัก = / tmp Sub Dir = ABCD (ไดเรกทอรีย่อยสี่แห่ง)


2
ตกลงโปรดแสดงสคริปต์ของคุณให้เราทราบ ส่วนไหนของปัญหาที่ทำให้คุณมีปัญหา?
terdon

คำตอบ:


22

ใช้การforวนซ้ำ:

for d in $(find /path/to/dir -maxdepth 1 -type d)
do
  #Do something, the directory is accessible with $d:
  echo $d
done >output_file

/path/to/dirจะค้นหาเฉพาะไดเรกทอรีย่อยของไดเรกทอรี โปรดทราบว่าตัวอย่างง่ายๆข้างต้นจะล้มเหลวหากชื่อไดเรกทอรีมีช่องว่างหรืออักขระพิเศษ แนวทางที่ปลอดภัยกว่าคือ:

find /tmp -maxdepth 1 -type d -print0 |
  while IFS= read -rd '' dir; do echo "$dir"; done

หรือในธรรมดาbash:

for d in /path/to/dir/*; do
  if [ -d "$d" ]; then
    echo "$d"
  fi
done

(โปรดทราบว่าตรงกันข้ามกับfindที่พิจารณา symlinks ไปยังไดเรกทอรีและแยกออกที่ซ่อนอยู่)


1
อย่างน้อยก็มีข้อ จำกัด และความเสี่ยงที่เกี่ยวข้องกับการประมวลผลผลลัพธ์findเช่นนั้น
Stéphane Chazelas

สวัสดี ... ฉันพยายามเรียกใช้ลูป for d ใน $ (find / backup / ASHISH -maxdepth 1 -type d) ทำ ls -l | awk '{พิมพ์ $ 9}' | grep CC * _ date +"%m%d20%Y"| xargs echo echo echo $ d
Ashish

สวัสดี ... ฉันพยายามลูปด้านล่าง สำหรับ d in $ (ค้นหา / backup / ASHISH -maxdepth 1 -type d) ทำ ls -l | awk '{พิมพ์ $ 9}' | grep CC * _ date +"%m%d20%Y"| xargs echo echo $ d ผลลัพธ์ที่คาดหวังคือ ls -ltr จากไดเรกทอรีย่อยทั้งหมด . เหนือวงไม่ทำงาน
Ashish

1

ฉันเป็นbashมือใหม่ แต่เป็นทหารผ่านศึกของ UN * X แม้ว่าไม่ต้องสงสัยเลยว่าสิ่งนี้สามารถทำได้ในสคริปต์เชลล์ของ Bash แต่ในอดีตเราเคยfind [-maxdepth <levels>] <start-dir> -exec <command> ;ประสบความสำเร็จ คุณสามารถทำman findและเล่นไปเรื่อย ๆ จนกว่าจะมีคนบอกคุณว่าจะทำยังไงbash!


ฉันภูมิใจมากที่คำตอบ "เค้าร่าง" ของฉันที่นี่ได้รับการโหวต อย่างไรก็ตามทำไมคำตอบของ @chaos ด้านล่างจึงได้รับการลงคะแนน (ในฐานะผู้มาใหม่ในบอร์ดนี้ฉันไม่สามารถโพสต์ความคิดเห็นนี้กับคำตอบของเขาได้เฉพาะกับตัวเอง) ข้อเสนอแนะที่สองของเขาถูกต้องสำหรับเชลล์สคริปต์โซลูชันและหลีกเลี่ยงค่าใช้จ่ายในการรันfindคำสั่งภายนอก
JonBrave

ที่สองของเขาถูกต้องแน่นอน คำสั่งแรกของเขาจะล้มเหลวหากชื่อไดเรกทอรีมีช่องว่างหรืออักขระพิเศษ (เช่นเครื่องหมายแบ็กสแลช) ดูการแก้ไขที่ฉันทำกับคำตอบของเขาสำหรับรุ่นที่ปลอดภัย
terdon

ฉันเห็นด้วย. มันเป็นคำตอบที่สองของเขาที่มี แต่เชลล์ที่ฉันชื่นชม
JonBrave

ฉันรู้ว่าฉันแค่อธิบาย downvote (ซึ่งฉันไม่ได้โยน)
terdon

ฉันโยนมันทิ้ง $(find...)สิ่งคือการปฏิบัติที่ไม่ดี
Stéphane Chazelas

1

ดูเหมือนว่าคุณต้องการชื่อไฟล์ภายใต้แต่ละตำบล ls -l | awkไม่เพียงพอที่แข็งแกร่งสำหรับสิ่งที่ถ้าชื่อไฟล์เหล่านั้นประกอบด้วยช่องว่างและ / หรือการขึ้นบรรทัดใหม่? ด้านล่างfindจะใช้งานได้แม้สำหรับfinddonot ที่เกิดขึ้นกับ-maxdepthพวกเขา:

find . ! -name . -type d -prune -exec sh -c '
   cd "$1" && \
   find "." ! -name . -prune  -type f
' {} {} \;

0

ฉันได้ทางออกแล้ว คำสั่ง find ด้านล่างตรงตามความต้องการของฉัน

find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && ls -l |awk '{ print $9 }' |grep `date +"%m%d%Y"`|xargs echo" \;

0

นอกจากนี้ยังสามารถใช้ ls, grep และ tr

for dir in $(ls -1FA | grep / | tr -d /); do echo $dir/something; done

ls -1FA | grep / | tr -d / | while IFS= read -r TD; do echo $TD/something; done

du / sed ยังสามารถใช้เป็นตัวเลือกได้หาก ls ของคุณไม่มีตัวเลือกด้านบน

du --max-depth=1 | sed -e 's/^.*\.\///' | grep -v '\.$'

มันอาจเป็นสิ่งสำคัญที่จะต้องทราบตัวอย่างเหล่านี้กลับไดเรกทอรีที่ซ่อนอยู่และไม่รวมไดเรกทอรีหลักและไดเรกทอรีปัจจุบัน


1
(1)  lsเขียนหนึ่งไฟล์ต่อบรรทัด ( -1ตัวเลือกที่ระบุ) โดยค่าเริ่มต้นเมื่อเอาต์พุตมาตรฐานคือไพพ์ (ดังนั้นคำตอบของคุณจึงไม่จำเป็น) (2) การแยกวิเคราะห์การส่งออกของlsเป็นความคิดที่ไม่ดี - เห็นนี้และนี้ คำตอบแรกของคุณจะล้มเหลวหากไดเรกทอรีมีช่องว่าง (หรือขึ้นบรรทัดใหม่) ในชื่อของพวกเขาและทั้งหมดจะล้มเหลวหากพวกเขามีบรรทัดใหม่ในชื่อของพวกเขา (3) คุณควรอ้างอิงตัวแปรของเชลล์ (เช่น"$dir") เว้นแต่คุณไม่มีเหตุผลที่ดีที่จะทำและคุณแน่ใจว่าคุณรู้ว่าคุณกำลังทำอะไรอยู่
สกอตต์

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