วิธีสำรวจแผนผังไดเรกทอรีบน Linux

เผยแพร่แล้ว: 2022-07-21
แล็ปท็อป Linux แสดง bash prompt
fatmawati achmad zaenuri/Shutterstock.com

ไดเร็กทอรีบน Linux ช่วยให้คุณสามารถจัดกลุ่มไฟล์ในคอลเล็กชันที่แยกจากกัน ข้อเสียคือการย้ายจากไดเร็กทอรีไปยังไดเร็กทอรีเพื่อทำงานซ้ำ ๆ นั้นน่าเบื่อหน่าย นี่คือวิธีการทำให้เป็นอัตโนมัติ

ทั้งหมดเกี่ยวกับไดเรกทอรี

คำสั่งแรกที่คุณเรียนรู้เมื่อคุณคุ้นเคยกับ Linux น่าจะเป็น ls แต่ cd จะไม่อยู่เบื้องหลัง การทำความเข้าใจไดเร็กทอรีและวิธีการย้ายไปรอบๆ โดยเฉพาะอย่างยิ่งไดเร็กทอรีย่อยที่ซ้อนกัน เป็นส่วนพื้นฐานในการทำความเข้าใจวิธีที่ลีนุกซ์จัดระเบียบตัวเอง และวิธีที่คุณสามารถจัดระเบียบงานของคุณเองเป็นไฟล์ ไดเร็กทอรี และไดเร็กทอรีย่อย

โครงสร้างไดเร็กทอรี Linux, อธิบาย
ที่เกี่ยวข้อง โครงสร้างไดเร็กทอรี Linux, อธิบาย

การเข้าใจแนวคิดของแผนผังไดเร็กทอรี—และวิธีการย้ายไปมาระหว่างไดเร็กทอรี—เป็นหนึ่งในเหตุการณ์สำคัญเล็กๆ น้อยๆ มากมายที่คุณผ่านเมื่อคุณทำความคุ้นเคยกับภูมิทัศน์ของ Linux การใช้ cd พร้อมพาธจะนำคุณไปยังไดเร็กทอรีนั้น ทางลัดเช่น cd ~ หรือ cd ด้วยตัวเองจะนำคุณกลับไปที่โฮมไดเร็กตอรี่ของคุณ และ cd .. จะย้ายคุณขึ้นหนึ่งระดับในแผนผังไดเร็กทอรี เรียบง่าย.

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

คำสั่งบางคำสั่ง เช่น ls มีตัวเลือกบรรทัดคำสั่งที่บังคับให้ทำงาน แบบเรียกซ้ำ หมายความว่าคำสั่งเหล่านั้นเริ่มต้นในไดเร็กทอรีเดียวและทำงานอย่างมีระเบียบผ่านแผนผังไดเร็กทอรีทั้งหมดด้านล่างไดเร็กทอรีนั้น สำหรับ ls มันคือตัวเลือก -R (แบบเรียกซ้ำ)

หากคุณต้องการใช้คำสั่งที่ไม่สนับสนุนการเรียกซ้ำ คุณต้องจัดเตรียมฟังก์ชันแบบเรียกซ้ำด้วยตนเอง นี่คือวิธีการทำเช่นนั้น

ที่เกี่ยวข้อง: 37 คำสั่ง Linux ที่สำคัญที่คุณควรรู้

คำสั่งต้นไม้

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

คุณจะต้องติดตั้ง tree

บน Ubuntu คุณต้องพิมพ์:

 sudo apt ติดตั้งต้นไม้ 

การติดตั้งต้นไม้บน Ubuntu

บน Fedora ให้ใช้:

 sudo dnf ติดตั้งต้นไม้ 

การติดตั้งต้นไม้บน Fedora

บน Manjaro คำสั่งคือ:

 sudo pacman -Sy tree 

การติดตั้งต้นไม้บน Manjaro

การใช้ tree ที่ไม่มีพารามิเตอร์จะดึงแผนผังด้านล่างไดเร็กทอรีปัจจุบัน

 ต้นไม้ 

เรียกใช้ทรีในไดเร็กทอรีปัจจุบัน

คุณสามารถส่งพาธไปยัง tree รีบนบรรทัดคำสั่งได้

 งานต้นไม้ 

รันทรีบนไดเร็กทอรีที่ระบุ

ตัวเลือก -d (ไดเร็กทอรี) ไม่รวมไฟล์และแสดงเฉพาะไดเร็กทอรี

 ต้นไม้ -d งาน 

ต้นไม้ทำงานและแสดงเฉพาะไดเรกทอรี

นี่เป็นวิธีที่สะดวกที่สุดในการมองเห็นโครงสร้างของไดเร็กทอรีที่ชัดเจน แผนผังไดเร็กทอรีที่แสดงในที่นี้คือแผนผังที่ใช้ในตัวอย่างต่อไปนี้ มีไฟล์ข้อความห้าไฟล์และไดเรกทอรีแปดรายการ

อย่าแยกวิเคราะห์ผลลัพธ์จาก ls ไปยัง Traverse Directory

ความคิดแรกของคุณอาจเป็นได้ว่า ถ้า ls สามารถสำรวจแผนผังไดเร็กทอรีแบบเรียกซ้ำได้ เหตุใดจึงไม่ใช้ ls เพื่อทำสิ่งนั้นและไพพ์เอาต์พุตไปยังคำสั่งอื่นๆ ที่แยกวิเคราะห์ไดเร็กทอรีและดำเนินการบางอย่าง

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

คุณอาจไม่เคยรู้เท่าทันสร้างชื่อไดเร็กทอรีที่ดูผิดปกติเช่นนี้ แต่อาจมีข้อผิดพลาดในสคริปต์หรือแอปพลิเคชัน

ชื่อไดเรกทอรีที่แปลกประหลาด

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

การใช้คำสั่ง find

คำสั่ง find มีความสามารถในการเรียกซ้ำในตัว และยังมีความสามารถในการเรียกใช้คำสั่งสำหรับเราอีกด้วย สิ่งนี้ทำให้เราสร้างสายการบินเดียวที่ทรงพลัง หากเป็นสิ่งที่คุณต้องการใช้ในอนาคต คุณสามารถเปลี่ยนสายการบินเดียวเป็นนามแฝงหรือฟังก์ชันเชลล์

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

 ค้นหางาน -type d -execdir echo "ใน:" {} \; 

ใช้คำสั่ง find เพื่อค้นหาไดเร็กทอรีแบบเรียกซ้ำ

คุณสามารถดูตามลำดับที่ไดเร็กทอรีแสดง การค้นหาดำเนินไปอย่างไรในแผนผัง โดยการเปรียบเทียบผลลัพธ์จากคำสั่ง tree กับผลลัพธ์จาก find one-liner คุณจะเห็นว่า find ค้นหาแต่ละไดเร็กทอรีและไดเร็กทอรีย่อยอย่างไร จนกระทั่งพบไดเร็กทอรีที่ไม่มีไดเร็กทอรีย่อย จากนั้นจะกลับขึ้นระดับหนึ่งและทำการค้นหาต่อในระดับนั้น

นี่คือวิธีการสร้างคำสั่ง

  • find : คำสั่ง find
  • งาน : ไดเร็กทอรีสำหรับเริ่มการค้นหา นี่อาจเป็นพาธ
  • -type d : เรากำลังมองหาไดเร็กทอรี
  • -execdir : เราจะรันคำสั่งในแต่ละไดเร็กทอรีที่เราพบ
  • echo “In:” {} : นี่คือคำสั่ง เราเพียงแค่สะท้อนชื่อของไดเร็กทอรีไปยังหน้าต่างเทอร์มินัล “{}” เป็นชื่อของไดเร็กทอรีปัจจุบัน
  • \; : นี่คือเครื่องหมายอัฒภาคที่ใช้เพื่อยุติคำสั่ง เราจำเป็นต้องหลีกเลี่ยงมันด้วยแบ็กสแลชเพื่อไม่ให้ Bash ตีความโดยตรง

ด้วยการเปลี่ยนแปลงเล็กน้อย เราสามารถทำให้คำสั่ง find ส่งคืนไฟล์ที่ตรงกับคำใบ้การค้นหา เราจำเป็นต้องรวมตัวเลือก -name และคำใบ้การค้นหา ในตัวอย่างนี้ เรากำลังค้นหาไฟล์ข้อความที่ตรงกับ “*.txt” และสะท้อนชื่อไปยังหน้าต่างเทอร์มินัล

 ค้นหาชื่องาน "*.txt" -type f -execdir echo "Found:" {} \; 

ใช้คำสั่ง find เพื่อค้นหาไฟล์ซ้ำๆ

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

คำสั่งนี้นับบรรทัดในไฟล์ข้อความทั้งหมดในไดเร็กทอรีเริ่มต้นและไดเร็กทอรีย่อย

 หางาน -name "*.txt" -type f -execdir wc -l {} \; 

ใช้ find ด้วยคำสั่ง wc

ที่เกี่ยวข้อง: วิธีใช้คำสั่ง 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 

การทำให้สคริปต์ recurse.sh เรียกทำงานได้

สคริปต์ตั้งค่าตัวเลือกเชลล์สองแบบคือ dotglob และ nullglob

การตั้งค่า dotglob หมายถึงชื่อไฟล์และไดเร็กทอรีที่ขึ้นต้นด้วยจุด “ . ” จะถูกส่งคืนเมื่อมีการขยายคำค้นหาโดยใช้สัญลักษณ์แทน นี่หมายความว่าเรากำลังรวมไฟล์และไดเรกทอรีที่ซ่อนอยู่ในผลการค้นหาของเรา

การตั้งค่า nullglob หมายถึงรูปแบบการค้นหาที่ไม่พบผลลัพธ์ใด ๆ จะถือว่าเป็นสตริงว่างหรือเป็นค่าว่าง พวกเขาไม่ได้ตั้งค่าเริ่มต้นให้กับข้อความค้นหาเอง กล่าวอีกนัยหนึ่ง หากเรากำลังค้นหาทุกอย่างในไดเร็กทอรีโดยใช้สัญลักษณ์แทนดอกจัน “ * “ แต่ไม่มีผลลัพธ์ใดๆ เราจะได้รับสตริงที่เป็นค่าว่างแทนสตริงที่มีเครื่องหมายดอกจัน ซึ่งจะป้องกันไม่ให้สคริปต์พยายามเปิดไดเร็กทอรีชื่อ "*" โดยไม่ได้ตั้งใจ หรือถือว่า "*" เป็นชื่อไฟล์

ถัดไป จะกำหนดฟังก์ชันที่เรียกว่าแบบเรียก recursive นี่คือสิ่งที่น่าสนใจเกิดขึ้น

มีการประกาศตัวแปรสองตัว เรียกว่า current_dir และ dir_or_file เหล่านี้เป็นตัวแปรท้องถิ่นและสามารถอ้างอิงได้ภายในฟังก์ชันเท่านั้น

ตัวแปรที่เรียกว่า $1 ยังถูกใช้ในฟังก์ชันอีกด้วย นี่เป็นพารามิเตอร์แรก (และเท่านั้น) ที่ส่งผ่านไปยังฟังก์ชันเมื่อมีการเรียกใช้

สีรองพื้น: Bash Loops: for, while, and until
รอง พื้นที่เกี่ยวข้อง : Bash Loops: for, while, and until

สคริปต์ใช้ 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 งาน 

กำลังประมวลผลไดเร็กทอรีจากลึกที่สุดไปตื้นที่สุด

คราวนี้ไดเร็กทอรีมีคำสั่งที่ใช้กับไดเร็กทอรีจากระดับที่ลึกที่สุดก่อน โดยทำงานสำรองกิ่งก้านของทรี ไดเร็กทอรีที่ส่งผ่านเมื่อพารามิเตอร์ของสคริปต์ถูกประมวลผลเป็นครั้งสุดท้าย

หากการประมวลผลไดเร็กทอรีที่ลึกกว่าเป็นสิ่งสำคัญก่อน นี่คือวิธีที่คุณสามารถทำได้

การเรียกซ้ำเป็นเรื่องแปลก

มันเหมือนกับการโทรหาตัวเองโดยใช้โทรศัพท์ของตัวเอง และฝากข้อความให้ตัวเองเพื่อบอกตัวเองว่าครั้งหน้าจะพบกับคุณครั้งต่อไป—ซ้ำแล้วซ้ำเล่า

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

ที่เกี่ยวข้อง: การเรียกซ้ำในการเขียนโปรแกรมคืออะไร และคุณใช้งานอย่างไร