วนซ้ำผ่านโฟลเดอร์และไฟล์รายการ


14

ฉันมีโฟลเดอร์ชื่อ 'ตัวอย่าง' และมันมี 3 ไฟล์อยู่ในนั้น ฉันต้องการเขียนเชลล์สคริปต์ซึ่งจะอ่านไฟล์เหล่านี้ภายในโฟลเดอร์ตัวอย่างและโพสต์ไปยังไซต์ HTTP โดยใช้ curl

ฉันเขียนสิ่งต่อไปนี้เพื่อแสดงรายการไฟล์ภายในโฟลเดอร์:

for dir in sample/*; do
        echo $dir;
        done

แต่มันให้ผลลัพธ์ต่อไปนี้กับฉัน:

sample/log

sample/clk

sample/demo

มันกำลังแนบโฟลเดอร์แม่ในนั้น ฉันต้องการผลลัพธ์ดังนี้ (ไม่มีชื่อโฟลเดอร์หลัก)

log

clk

demo

ฉันจะทำสิ่งนี้ได้อย่างไร


1
ใช้ 'cd' ก่อน หากคุณต้องการ 'ขด' คุณยังคงต้องใส่ไดเรกทอรี นอกจากนี้คุณสามารถใช้echo ${dir##*/}เพื่อปิดเส้นทาง
eexpress

คำตอบ:


32

ใช้basenameเพื่อตัดพา ธ นำหน้าออกจากไฟล์:

for file in sample/*; do
    echo "$(basename "$file")"
done

แม้ว่าทำไมไม่:

( cd sample; ls )

3

สมมติว่าเชลล์ของคุณรองรับคุณสามารถใช้การขยายพารามิเตอร์

for path in sample/*; do
    printf -- '%s\n' "${path##*/}"
done

หรือคุณสามารถเปลี่ยนเป็นไดเรกทอรีนั้นและทำรายชื่อที่นั่น


1
--ไม่จำเป็นต้องที่นี่ อาร์กิวเมนต์แรกคือสตริงคงที่โดยไม่มีขีดกลาง
Kusalananda

นอกจากนี้ยัง${parameter##pattern}รองรับ POSIX เชลล์ทั้งหมด
Kusalananda

2

เนื่องจากระบบ * nix อนุญาตให้ตัวละครเกือบทุกตัวเป็นส่วนหนึ่งของชื่อไฟล์ (รวมถึงช่องว่าง, การขึ้นบรรทัดใหม่, คอมม่า, สัญลักษณ์ไพพ์, ฯลฯ ) คุณไม่ควรแยกเอาต์พุตของคำสั่ง "ls" ในเชลล์สคริปต์ มันไม่น่าเชื่อถือ ดูทำไมคุณไม่ควรแยกการส่งออกของคำสั่ง ls

ใช้ "ค้นหา" เพื่อสร้างรายการไฟล์ หากคุณกำลังใช้ Bash คุณสามารถแทรกผลลัพธ์ของ "find" ลงในอาร์เรย์ ตัวอย่างด้านล่างด้วยข้อแม้ที่ฉันใช้คำสั่ง "curl" ที่ไม่ทำงาน!

searchDir="sample/"
oldFiles=()
while IFS= read -r -d $'\0' foundFile; do
    oldFiles+=("$foundFile")
done < <(find "$searchDir" -maxdepth 1 -type f -print0 2> /dev/null)

if [[ ${#oldFiles[@]} -ne 0 ]]; then
    for file in "${oldFiles[@]}"; do
        curl -F data=@"$file" UPLOAD_ADDRESS
    done
fi

ไดเรกทอรีที่นี่คืออะไร? $ '\ 0' ฉันต้องการที่จะผ่านไดเรกทอรีที่อยู่ในตัวแปร ...
Soylent เกรแฮม

searchDir เป็นตัวแปรไดเรกทอรี "-d $ '\ 0'" ตั้งค่าตัวคั่นของคำสั่ง read เป็น null
bb_referee

ฉันจะบรรลุสิ่งเดียวกันในเปลือกหอยได้อย่างไร? ฉันใช้ #! / bin / sh
Ayusman

1

มันขึ้นอยู่กับสิ่งที่คุณต้องการจะทำกับไดเรกทอรี

หากต้องการพิมพ์ชื่อโดยไม่ต้องตรวจสอบว่าเป็นไดเรกทอรีคุณสามารถใช้ ls:

ls -1 sample

จะดีกว่าเพราะคุณสามารถใช้ตัวกรอง:

find sample -type d -maxdepth 1 -printf '%f\n'

หากคุณต้องการรันคำสั่งบนไฟล์คุณควรใช้ find และไม่ใช่ a for for loop:

find sample -type d -maxdepth 1 -exec basename {} \;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.