ค้นหาไฟล์ที่มีนามสกุลเฉพาะซ้ำ ๆ


437

ฉันพยายามค้นหาไฟล์ทั้งหมดที่มีนามสกุลเฉพาะในไดเรกทอรีและไดเรกทอรีย่อยด้วยทุบตีของฉัน (ล่าสุด Ubuntu LTS Release)

นี่คือสิ่งที่เขียนในไฟล์สคริปต์:

#!/bin/bash

directory="/home/flip/Desktop"
suffix="in"

browsefolders ()
  for i in "$1"/*; 
  do
    echo "dir :$directory"
    echo "filename: $i"
    #   echo ${i#*.}
    extension=`echo "$i" | cut -d'.' -f2`
    echo "Erweiterung $extension"
    if     [ -f "$i" ]; then        

        if [ $extension == $suffix ]; then
            echo "$i ends with $in"

        else
            echo "$i does NOT end with $in"
        fi
    elif [ -d "$i" ]; then  
    browsefolders "$i"
    fi
  done
}
browsefolders  "$directory"

น่าเสียดายที่เมื่อฉันเริ่มสคริปต์นี้ใน terminal มันบอกว่า:

[: 29: in: unexpected operator

(ด้วย$extensionแทน'in' )

เกิดอะไรขึ้นที่นี่ข้อผิดพลาดอยู่ที่ไหน แต่วงเล็บปีกกานี้


2
ข้อผิดพลาดเกิดจาก '{'
shrewmouse

คำตอบ:


750
find $directory -type f -name "*.in"

สั้นกว่าทุกสิ่งเล็กน้อย (และปลอดภัยกว่า - เกี่ยวข้องกับช่องว่างในชื่อไฟล์และชื่อไดเรกทอรี)

สคริปต์ของคุณอาจล้มเหลวสำหรับรายการที่ไม่มี.ในชื่อทำให้$extensionว่างเปล่า


16
ใช่findจะเรียกซ้ำโดยปริยาย คุณสามารถ จำกัด ความลึกได้ถ้าต้องการ (ดูหน้า man)
Mat

1
ฉันต้องการส่งไฟล์ที่พบทั้งหมดเป็นอาร์กิวเมนต์ไปยังไฟล์ jar วิธีนี้สามารถทำได้?
พลิก

8
@flip: นั่นเป็นคำถามที่แตกต่าง โพสต์คำถามใหม่โดยมีรายละเอียดสิ่งที่คุณต้องการทำและสิ่งที่คุณได้ลองมาแล้ว
Mat

การแก้ไขเพียงเล็กน้อย: ใช้ '* .in' หรือ \ *. แทน "* .in" เนื่องจากเครื่องหมายอัญประกาศไม่ได้ป้องกันการขยายตัวของเชลล์ เช่นสคริปต์ของคุณจะทำงานไม่ถูกต้องหากมีไฟล์ที่มีนามสกุล. in อยู่ในไดเรกทอรีปัจจุบัน
Shnatsel

4
@Shnatsel: เครื่องหมายคำพูดคู่ป้องกันการขยายตัวของเชลล์ ลองดู
Mat

188
find {directory} -type f -name '*.extension'

ตัวอย่าง:หากต้องการค้นหาcsvไฟล์ทั้งหมดในไดเรกทอรีปัจจุบันและไดเรกทอรีย่อยให้ใช้:

find . -type f -name '*.csv'

60

ไวยากรณ์ที่ฉันใช้นั้นแตกต่างจากที่ @Matt แนะนำ:

find $directory -type f -name \*.in

(มันเป็นหนึ่งในการกดแป้นพิมพ์น้อยกว่า)


1
สคริปต์ของ Matt ยังไม่ทำงานหากมีไฟล์ที่มีนามสกุล. in อยู่ในไดเรกทอรีปัจจุบันในขณะที่คุณยังใช้งานได้ ดูstackoverflow.com/questions/5927369/…
Shnatsel

4
@Shnatsel ความคิดเห็นนี้ (และดังนั้นจึงเป็นของคุณ) ผิดธรรมดา
gniourf_gniourf

1
@gniourf_gniourf คุณควรให้ข้อมูลอ้างอิงสำหรับคำสั่งของคุณมิฉะนั้นคุณอาจโต้แย้งว่า: "ไม่คุณผิด" แต่ในความเป็นจริงคุณขวา: gnu.org/software/bash/manual/html_node/Double-Quotes.html
Murmel

@ user1885518: ฉันคิดว่ามันควรจะเป็นคนที่อ้างว่าสคริปต์ไม่ทำงานที่ควรให้ตัวอย่างที่สคริปต์ล้มเหลว นั่นคือสิ่งที่ฉันทำเมื่อฉันแสดงความคิดเห็นที่มีสคริปต์ที่เสียหาย: โดยปกติจะเกี่ยวกับคำพูดและชื่อไฟล์ที่มีช่องว่าง, การขึ้นบรรทัดใหม่, globs ฯลฯ และฉันอธิบายว่าทำไมมันถึงแตกสลายโดยเฉพาะ
gniourf_gniourf

2
การให้การอ้างอิงเป็นวิธีที่ดีในการอภิปรายเสมอไม่ได้ขึ้นอยู่กับว่าใครเป็นคนแรก เขาควรคุณควร
Murmel

14

โดยไม่ต้องใช้find:

du -a $directory | awk '{print $2}' | grep '\.in$'

3
grepไม่จำเป็นจริงๆที่นี่ awkมีนิพจน์ทั่วไปและสามารถ จำกัด ผลลัพธ์ให้มีค่าที่ตรงกับรูปแบบ
Kenster

วิธีนี้มีประโยชน์อย่างยิ่งหากคุณผ่านเทราไบต์ 100s คำสั่งค้นหาใช้เวลาในการประมวลผลนานเกินไป สิ่งนี้เริ่มต้นทันที
Protonova

1
awk|grepเป็นรูปแบบการต่อต้าน ให้ awk ทำการ grepping
Jens

10
  1. มีความเป็น{หลังจากที่หายไปbrowsefolders ()
  2. ทั้งหมด$inควรจะเป็น$suffix
  3. บรรทัดที่cutจะทำให้คุณได้รับเฉพาะส่วนตรงกลางของfront.middle.extensionทำให้คุณได้รับเพียงส่วนตรงกลางของคุณควรอ่านคู่มือการใช้งานเชลล์${varname%%pattern}และเพื่อน ๆ

ฉันถือว่าคุณทำเช่นนี้เป็นแบบฝึกหัดในการเขียนสคริปต์เชลล์มิฉะนั้น findโซลูชันที่เสนอมาแล้วเป็นวิธีที่จะไป

sh -n scriptnameเพื่อตรวจสอบไวยากรณ์เปลือกที่เหมาะสมโดยไม่ต้องใช้สคริปต์ใช้



7

แม้ว่าการใช้findคำสั่งจะมีประโยชน์ที่นี่เชลล์เองมีตัวเลือกเพื่อให้บรรลุความต้องการนี้โดยไม่ต้องใช้เครื่องมือของบุคคลที่สาม bashเปลือกยังมีตัวเลือกการสนับสนุน glob ขยายการใช้ที่คุณจะได้รับชื่อไฟล์ที่อยู่ภายใต้เส้นทาง recursive ว่าการแข่งขันที่มีส่วนขยายที่คุณต้องการ

ตัวเลือกเพิ่มเติมคือextglobสิ่งที่จะต้องตั้งค่าโดยใช้shoptตัวเลือกดังต่อไปนี้ ตัวเลือกจะเปิดใช้งานด้วยการ-sสนับสนุนและปิดการใช้งานด้วยเขา-uธง นอกจากนี้คุณสามารถใช้ตัวเลือกสองตัวเลือกมากกว่าเช่นnullglobที่ glob ที่ไม่ตรงกันถูกกวาดออกไปทั้งหมดแทนที่ด้วยชุดของคำศูนย์ และglobstarที่ช่วยให้สามารถเรียกคืนผ่านไดเรกทอรีทั้งหมด

shopt -s extglob nullglob globstar

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

ตัวอย่างเช่นเพื่อแสดงรายการ*.csvไฟล์ทั้งหมดในเส้นทางแบบเรียกซ้ำ

fileList=(**/*.csv)

ตัวเลือก**คือการเรียกคืนผ่านโฟลเดอร์ย่อยและ*.csvเป็นส่วนขยายแบบกลมเพื่อรวมไฟล์ของส่วนขยายที่กล่าวถึง ตอนนี้สำหรับการพิมพ์ไฟล์จริงเพียงทำ

printf '%s\n' "${fileList[@]}"

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

ls -1 -- **/*.csv

สิ่งนี้สามารถขยายได้มากเพื่อให้ตรงกับไฟล์หลาย ๆ ไฟล์เช่นไฟล์ที่ลงท้ายด้วยนามสกุลหลายไฟล์ (เช่นคล้ายกับการเพิ่มfindคำสั่งหลายแฟล็กในคำสั่ง) ยกตัวอย่างเช่นพิจารณากรณีที่จำเป็นต้องได้รับไฟล์ภาพ recursive ทั้งหมดคือส่วนขยาย*.gif, *.pngและ*.jpgสิ่งที่คุณจำเป็นต้องมี

ls -1 -- **/+(*.jpg|*.gif|*.png)

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

excludeResults=()
excludeResults=(**/!(*.jpg|*.gif|*.png))
printf '%s\n' "${excludeResults[@]}"

โครงสร้าง!()คือการดำเนินการเชิงลบที่จะไม่รวมนามสกุลไฟล์ใด ๆ ที่อยู่ในรายการและ|เป็นตัวดำเนินการสำรองเช่นเดียวกับที่ใช้ในไลบรารี Extended Regular Expressions เพื่อทำการจับคู่ OR ของ globs

หมายเหตุว่าสิ่งเหล่านี้สนับสนุนการขยาย glob ไม่สามารถใช้ได้ในบอร์นเชลล์ POSIX bashและหมดจดเฉพาะกับรุ่นล่าสุดของ ดังนั้นหากคุณกำลังพิจารณาความสามารถในการพกพาของสคริปต์ที่ทำงานบน POSIX และbashเชลล์ตัวเลือกนี้จะไม่ถูกต้อง


6

หากต้องการค้นหาpom.xmlไฟล์ทั้งหมดในไดเรกทอรีปัจจุบันของคุณและพิมพ์ไฟล์คุณสามารถใช้:

find . -name 'pom.xml' -print


0
for file in "${LOCATION_VAR}"/*.zip
do
  echo "$file"
done 

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