วิธีสำรวจแผนผังไดเรกทอรีบน Linux
เผยแพร่แล้ว: 2022-07-21
ไดเร็กทอรีบน Linux ช่วยให้คุณสามารถจัดกลุ่มไฟล์ในคอลเล็กชันที่แยกจากกัน ข้อเสียคือการย้ายจากไดเร็กทอรีไปยังไดเร็กทอรีเพื่อทำงานซ้ำ ๆ นั้นน่าเบื่อหน่าย นี่คือวิธีการทำให้เป็นอัตโนมัติ
ทั้งหมดเกี่ยวกับไดเรกทอรี
คำสั่งแรกที่คุณเรียนรู้เมื่อคุณคุ้นเคยกับ Linux น่าจะเป็น ls
แต่ cd
จะไม่อยู่เบื้องหลัง การทำความเข้าใจไดเร็กทอรีและวิธีการย้ายไปรอบๆ โดยเฉพาะอย่างยิ่งไดเร็กทอรีย่อยที่ซ้อนกัน เป็นส่วนพื้นฐานในการทำความเข้าใจวิธีที่ลีนุกซ์จัดระเบียบตัวเอง และวิธีที่คุณสามารถจัดระเบียบงานของคุณเองเป็นไฟล์ ไดเร็กทอรี และไดเร็กทอรีย่อย
การเข้าใจแนวคิดของแผนผังไดเร็กทอรี—และวิธีการย้ายไปมาระหว่างไดเร็กทอรี—เป็นหนึ่งในเหตุการณ์สำคัญเล็กๆ น้อยๆ มากมายที่คุณผ่านเมื่อคุณทำความคุ้นเคยกับภูมิทัศน์ของ Linux การใช้ cd
พร้อมพาธจะนำคุณไปยังไดเร็กทอรีนั้น ทางลัดเช่น cd ~
หรือ cd
ด้วยตัวเองจะนำคุณกลับไปที่โฮมไดเร็กตอรี่ของคุณ และ cd ..
จะย้ายคุณขึ้นหนึ่งระดับในแผนผังไดเร็กทอรี เรียบง่าย.
อย่างไรก็ตาม ไม่มีวิธีง่ายๆ ในการรันคำสั่งในไดเร็กทอรีทั้งหมดของแผนผังไดเร็กทอรี มีหลายวิธีที่เราสามารถบรรลุฟังก์ชันดังกล่าวได้ แต่ไม่มีคำสั่ง Linux มาตรฐานสำหรับจุดประสงค์นั้นโดยเฉพาะ
คำสั่งบางคำสั่ง เช่น ls
มีตัวเลือกบรรทัดคำสั่งที่บังคับให้ทำงาน แบบเรียกซ้ำ หมายความว่าคำสั่งเหล่านั้นเริ่มต้นในไดเร็กทอรีเดียวและทำงานอย่างมีระเบียบผ่านแผนผังไดเร็กทอรีทั้งหมดด้านล่างไดเร็กทอรีนั้น สำหรับ ls
มันคือตัวเลือก -R
(แบบเรียกซ้ำ)
หากคุณต้องการใช้คำสั่งที่ไม่สนับสนุนการเรียกซ้ำ คุณต้องจัดเตรียมฟังก์ชันแบบเรียกซ้ำด้วยตนเอง นี่คือวิธีการทำเช่นนั้น
ที่เกี่ยวข้อง: 37 คำสั่ง Linux ที่สำคัญที่คุณควรรู้
คำสั่งต้นไม้
คำสั่ง tree
ไม่ได้ช่วยเราเกี่ยวกับงานที่ทำอยู่ แต่มันทำให้ง่ายต่อการดูโครงสร้างของแผนผังไดเร็กทอรี มันดึงทรีในหน้าต่างเทอร์มินัลเพื่อให้เราสามารถรับภาพรวมทันทีของไดเร็กทอรีและไดเร็กทอรีย่อยที่ประกอบเป็นแผนผังไดเร็กทอรี และตำแหน่งที่สัมพันธ์กันในแผนผัง
คุณจะต้องติดตั้ง tree
บน Ubuntu คุณต้องพิมพ์:
sudo apt ติดตั้งต้นไม้
บน Fedora ให้ใช้:
sudo dnf ติดตั้งต้นไม้
บน Manjaro คำสั่งคือ:
sudo pacman -Sy tree
การใช้ tree
ที่ไม่มีพารามิเตอร์จะดึงแผนผังด้านล่างไดเร็กทอรีปัจจุบัน
ต้นไม้
คุณสามารถส่งพาธไปยัง tree
รีบนบรรทัดคำสั่งได้
งานต้นไม้
ตัวเลือก -d
(ไดเร็กทอรี) ไม่รวมไฟล์และแสดงเฉพาะไดเร็กทอรี
ต้นไม้ -d งาน
นี่เป็นวิธีที่สะดวกที่สุดในการมองเห็นโครงสร้างของไดเร็กทอรีที่ชัดเจน แผนผังไดเร็กทอรีที่แสดงในที่นี้คือแผนผังที่ใช้ในตัวอย่างต่อไปนี้ มีไฟล์ข้อความห้าไฟล์และไดเรกทอรีแปดรายการ
อย่าแยกวิเคราะห์ผลลัพธ์จาก ls ไปยัง Traverse Directory
ความคิดแรกของคุณอาจเป็นได้ว่า ถ้า ls
สามารถสำรวจแผนผังไดเร็กทอรีแบบเรียกซ้ำได้ เหตุใดจึงไม่ใช้ ls
เพื่อทำสิ่งนั้นและไพพ์เอาต์พุตไปยังคำสั่งอื่นๆ ที่แยกวิเคราะห์ไดเร็กทอรีและดำเนินการบางอย่าง
การแยกวิเคราะห์ผลลัพธ์ของ ls
ถือเป็นการปฏิบัติที่ไม่ดี เนื่องจากความสามารถของ Linux ในการสร้างชื่อไฟล์และไดเร็กทอรีที่มีอักขระแปลก ๆ ทุกประเภท จึงเป็นเรื่องยากมากที่จะสร้างตัวแยกวิเคราะห์ทั่วไปที่ถูกต้องในระดับสากล
คุณอาจไม่เคยรู้เท่าทันสร้างชื่อไดเร็กทอรีที่ดูผิดปกติเช่นนี้ แต่อาจมีข้อผิดพลาดในสคริปต์หรือแอปพลิเคชัน
การแยกวิเคราะห์ชื่อไฟล์และไดเร็กทอรีที่ถูกต้องแต่ถือว่าไม่ดีมักเกิดข้อผิดพลาดได้ มีวิธีการอื่นที่เราสามารถใช้ได้ที่ปลอดภัยกว่าและมีประสิทธิภาพมากกว่าการอาศัยการตีความผลลัพธ์ของ ls
การใช้คำสั่ง find
คำสั่ง find
มีความสามารถในการเรียกซ้ำในตัว และยังมีความสามารถในการเรียกใช้คำสั่งสำหรับเราอีกด้วย สิ่งนี้ทำให้เราสร้างสายการบินเดียวที่ทรงพลัง หากเป็นสิ่งที่คุณต้องการใช้ในอนาคต คุณสามารถเปลี่ยนสายการบินเดียวเป็นนามแฝงหรือฟังก์ชันเชลล์
คำสั่งนี้วนซ้ำผ่านแผนผังไดเร็กทอรีโดยมองหาไดเร็กทอรี ทุกครั้งที่พบไดเร็กทอรี มันจะพิมพ์ชื่อของไดเร็กทอรีและทำการค้นหาซ้ำภายในไดเร็กทอรีนั้น เมื่อค้นหาหนึ่งไดเร็กทอรีเสร็จแล้ว มันจะออกจากไดเร็กทอรีนั้นและดำเนินการค้นหาต่อในไดเร็กทอรีหลัก
ค้นหางาน -type d -execdir echo "ใน:" {} \;
คุณสามารถดูตามลำดับที่ไดเร็กทอรีแสดง การค้นหาดำเนินไปอย่างไรในแผนผัง โดยการเปรียบเทียบผลลัพธ์จากคำสั่ง tree
กับผลลัพธ์จาก find
one-liner คุณจะเห็นว่า find
ค้นหาแต่ละไดเร็กทอรีและไดเร็กทอรีย่อยอย่างไร จนกระทั่งพบไดเร็กทอรีที่ไม่มีไดเร็กทอรีย่อย จากนั้นจะกลับขึ้นระดับหนึ่งและทำการค้นหาต่อในระดับนั้น
นี่คือวิธีการสร้างคำสั่ง
- find : คำสั่ง
find
- งาน : ไดเร็กทอรีสำหรับเริ่มการค้นหา นี่อาจเป็นพาธ
- -type d : เรากำลังมองหาไดเร็กทอรี
- -execdir : เราจะรันคำสั่งในแต่ละไดเร็กทอรีที่เราพบ
- echo “In:” {} : นี่คือคำสั่ง เราเพียงแค่สะท้อนชื่อของไดเร็กทอรีไปยังหน้าต่างเทอร์มินัล “{}” เป็นชื่อของไดเร็กทอรีปัจจุบัน
- \; : นี่คือเครื่องหมายอัฒภาคที่ใช้เพื่อยุติคำสั่ง เราจำเป็นต้องหลีกเลี่ยงมันด้วยแบ็กสแลชเพื่อไม่ให้ Bash ตีความโดยตรง
ด้วยการเปลี่ยนแปลงเล็กน้อย เราสามารถทำให้คำสั่ง find ส่งคืนไฟล์ที่ตรงกับคำใบ้การค้นหา เราจำเป็นต้องรวมตัวเลือก -name และคำใบ้การค้นหา ในตัวอย่างนี้ เรากำลังค้นหาไฟล์ข้อความที่ตรงกับ “*.txt” และสะท้อนชื่อไปยังหน้าต่างเทอร์มินัล

ค้นหาชื่องาน "*.txt" -type f -execdir echo "Found:" {} \;
ไม่ว่าคุณจะค้นหาไฟล์หรือไดเร็กทอรีขึ้นอยู่กับสิ่งที่คุณต้องการบรรลุ หากต้องการรันคำสั่ง ภายในแต่ละไดเร็กทอรี ให้ใช้ -type d
ในการรันคำสั่งใน แต่ละไฟล์ที่ตรงกัน ให้ใช้ -type f
คำสั่งนี้นับบรรทัดในไฟล์ข้อความทั้งหมดในไดเร็กทอรีเริ่มต้นและไดเร็กทอรีย่อย
หางาน -name "*.txt" -type f -execdir wc -l {} \;
ที่เกี่ยวข้อง: วิธีใช้คำสั่ง find ใน Linux
สำรวจแผนผังไดเร็กทอรีด้วยสคริปต์
หากคุณต้องการสำรวจไดเร็กทอรีภายในสคริปต์ คุณสามารถใช้คำสั่ง find
ภายในสคริปต์ของคุณได้ หากคุณต้องการหรือเพียงแค่ต้องการทำการค้นหาซ้ำด้วยตัวเอง คุณก็สามารถทำได้เช่นกัน
#!/bin/bash shopt -s dotglob nullglob ฟังก์ชั่นเรียกซ้ำ { ท้องถิ่น current_dir dir_or_file สำหรับ current_dir ใน $1; ทำ echo "คำสั่งไดเรกทอรีสำหรับ:" $current_dir สำหรับ dir_or_file ใน "$current_dir"/*; ทำ ถ้า [[ -d $dir_or_file ]]; แล้ว เรียกซ้ำ "$dir_or_file" อื่น wc $dir_or_file fi เสร็จแล้ว เสร็จแล้ว } เรียกซ้ำ "$1"
คัดลอกข้อความลงในโปรแกรมแก้ไขและบันทึกเป็น "recurse.sh" จากนั้นใช้คำสั่ง chmod
เพื่อให้ทำงานได้
chmod +x recurse.sh
สคริปต์ตั้งค่าตัวเลือกเชลล์สองแบบคือ dotglob
และ nullglob
การตั้งค่า dotglob
หมายถึงชื่อไฟล์และไดเร็กทอรีที่ขึ้นต้นด้วยจุด “ .
” จะถูกส่งคืนเมื่อมีการขยายคำค้นหาโดยใช้สัญลักษณ์แทน นี่หมายความว่าเรากำลังรวมไฟล์และไดเรกทอรีที่ซ่อนอยู่ในผลการค้นหาของเรา
การตั้งค่า nullglob
หมายถึงรูปแบบการค้นหาที่ไม่พบผลลัพธ์ใด ๆ จะถือว่าเป็นสตริงว่างหรือเป็นค่าว่าง พวกเขาไม่ได้ตั้งค่าเริ่มต้นให้กับข้อความค้นหาเอง กล่าวอีกนัยหนึ่ง หากเรากำลังค้นหาทุกอย่างในไดเร็กทอรีโดยใช้สัญลักษณ์แทนดอกจัน “ *
“ แต่ไม่มีผลลัพธ์ใดๆ เราจะได้รับสตริงที่เป็นค่าว่างแทนสตริงที่มีเครื่องหมายดอกจัน ซึ่งจะป้องกันไม่ให้สคริปต์พยายามเปิดไดเร็กทอรีชื่อ "*" โดยไม่ได้ตั้งใจ หรือถือว่า "*" เป็นชื่อไฟล์
ถัดไป จะกำหนดฟังก์ชันที่เรียกว่าแบบเรียก recursive
นี่คือสิ่งที่น่าสนใจเกิดขึ้น
มีการประกาศตัวแปรสองตัว เรียกว่า current_dir
และ dir_or_file
เหล่านี้เป็นตัวแปรท้องถิ่นและสามารถอ้างอิงได้ภายในฟังก์ชันเท่านั้น
ตัวแปรที่เรียกว่า $1
ยังถูกใช้ในฟังก์ชันอีกด้วย นี่เป็นพารามิเตอร์แรก (และเท่านั้น) ที่ส่งผ่านไปยังฟังก์ชันเมื่อมีการเรียกใช้
สคริปต์ใช้ for
ลูป อันหนึ่งซ้อนอยู่ภายในอีกอัน ตัวแรก (นอก) for
loop ใช้สำหรับสองสิ่ง
หนึ่งคือการเรียกใช้คำสั่งใด ๆ ที่คุณต้องการทำในแต่ละไดเร็กทอรี สิ่งที่เราทำที่นี่คือการสะท้อนชื่อของไดเร็กทอรีไปยังหน้าต่างเทอร์มินัล คุณสามารถใช้คำสั่งหรือลำดับคำสั่งใดๆ หรือเรียกใช้ฟังก์ชันสคริปต์อื่นได้
สิ่งที่สองที่ outer for loop ทำคือการตรวจสอบอ็อบเจ็กต์ระบบไฟล์ทั้งหมดที่สามารถค้นหาได้ ซึ่งจะเป็นไฟล์หรือไดเร็กทอรี นี่คือจุดประสงค์ของวง for
ในทางกลับกัน แต่ละไฟล์หรือชื่อไดเร็กทอรีจะถูกส่งผ่านไปยังตัวแปร dir_or_file
ตัวแปร dir_or_file
จะถูกทดสอบในคำสั่ง if เพื่อดูว่าเป็นไดเร็กทอรีหรือไม่
- ถ้าใช่ ฟังก์ชันจะเรียกตัวเองและส่งชื่อของไดเร็กทอรีเป็นพารามิเตอร์
- หากตัวแปร
dir_or_file
ไม่ใช่ไดเร็กทอรี จะต้องเป็นไฟล์ คำสั่งใดๆ ที่คุณต้องการใช้กับไฟล์สามารถเรียกได้จากส่วนคำสั่งelse
ของคำสั่งif
คุณยังสามารถเรียกใช้ฟังก์ชันอื่นภายในสคริปต์เดียวกันได้
บรรทัดสุดท้ายในสคริปต์เรียกฟังก์ชัน recursive
และส่งผ่านในพารามิเตอร์ บรรทัดคำสั่ง แรก $1
เป็นไดเร็กทอรีเริ่มต้นเพื่อค้นหา นี่คือสิ่งที่เริ่มต้นกระบวนการทั้งหมด
มาเรียกใช้สคริปต์กันเถอะ
./recurse.sh งาน
ไดเร็กทอรีถูกสำรวจ และจุดในสคริปต์ที่จะรันคำสั่งในแต่ละไดเร็กทอรีจะถูกระบุโดยบรรทัด "Directory command for:" ไฟล์ที่พบมีคำสั่ง wc
รันอยู่เพื่อนับบรรทัด คำ และอักขระ
ไดเร็กทอรีแรกที่ประมวลผลคือ "งาน" ตามด้วยไดเร็กทอรีแต่ละสาขาที่ซ้อนกันของแผนผัง
จุดที่น่าสนใจที่ควรทราบคือ คุณสามารถเปลี่ยนลำดับที่ประมวลผลไดเร็กทอรี โดยการย้ายคำสั่งเฉพาะไดเร็กทอรีจากด้านบนภายในสำหรับลูปไปอยู่ด้านล่าง
ให้ย้ายบรรทัด "Directory command for:" ไปที่หลัง done
inner for
loop
#!/bin/bash shopt -s dotglob nullglob ฟังก์ชันเรียกซ้ำ { ท้องถิ่น current_dir dir_or_file สำหรับ current_dir ใน $1; ทำ สำหรับ dir_or_file ใน "$current_dir"/*; ทำ ถ้า [[ -d $dir_or_file ]]; แล้ว เรียกซ้ำ "$dir_or_file" อื่น wc $dir_or_file fi เสร็จแล้ว echo "คำสั่งไดเรกทอรีสำหรับ:" $current_dir เสร็จแล้ว } เรียกซ้ำ "$1"
ตอนนี้เราจะเรียกใช้สคริปต์อีกครั้ง
./recurse.sh งาน
คราวนี้ไดเร็กทอรีมีคำสั่งที่ใช้กับไดเร็กทอรีจากระดับที่ลึกที่สุดก่อน โดยทำงานสำรองกิ่งก้านของทรี ไดเร็กทอรีที่ส่งผ่านเมื่อพารามิเตอร์ของสคริปต์ถูกประมวลผลเป็นครั้งสุดท้าย
หากการประมวลผลไดเร็กทอรีที่ลึกกว่าเป็นสิ่งสำคัญก่อน นี่คือวิธีที่คุณสามารถทำได้
การเรียกซ้ำเป็นเรื่องแปลก
มันเหมือนกับการโทรหาตัวเองโดยใช้โทรศัพท์ของตัวเอง และฝากข้อความให้ตัวเองเพื่อบอกตัวเองว่าครั้งหน้าจะพบกับคุณครั้งต่อไป—ซ้ำแล้วซ้ำเล่า
อาจต้องใช้ความพยายามบ้างก่อนที่คุณจะเข้าใจประโยชน์ของมัน แต่เมื่อคุณเข้าใจแล้ว คุณจะเห็นว่ามันเป็นวิธีการที่สวยงามโดยทางโปรแกรมเพื่อจัดการกับปัญหายากๆ
ที่เกี่ยวข้อง: การเรียกซ้ำในการเขียนโปรแกรมคืออะไร และคุณใช้งานอย่างไร