บนเครื่องลีนุกซ์ฉันต้องการสำรวจลำดับชั้นของโฟลเดอร์และรับรายการของนามสกุลไฟล์ที่แตกต่างกันทั้งหมดที่อยู่ภายใน
อะไรจะเป็นวิธีที่ดีที่สุดในการบรรลุเป้าหมายนี้จากเชลล์?
บนเครื่องลีนุกซ์ฉันต้องการสำรวจลำดับชั้นของโฟลเดอร์และรับรายการของนามสกุลไฟล์ที่แตกต่างกันทั้งหมดที่อยู่ภายใน
อะไรจะเป็นวิธีที่ดีที่สุดในการบรรลุเป้าหมายนี้จากเชลล์?
คำตอบ:
ลองใช้ (ไม่แน่ใจว่าเป็นวิธีที่ดีที่สุด แต่ใช้งานได้):
find . -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u
มันทำงานดังต่อไปนี้:
git ls-tree -r HEAD --name-only
แทนfind
find . -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort | uniq -c | sort -n
ไม่จำเป็นต้องใช้ท่อถึงsort
awk สามารถทำได้ทั้งหมด:
find . -type f | awk -F. '!a[$NF]++{print $NF}'
alias
คำสั่ง แต่คำสั่งตัวเองใช้คำพูดในคำสั่งค้นหาแล้ว ในการแก้ไขปัญหานี้ฉันจะใช้bash
ไวยากรณ์สตริงตามตัวอักษรดังนี้:alias file_ext=$'find . -type f -name "*.*" | awk -F. \'!a[$NF]++{print $NF}\''
maindir/test.dir/myfile
-printf "%f\n"
ไปยังจุดสิ้นสุดของคำสั่ง 'find' และเรียกใช้การทดสอบของคุณอีกครั้ง
เวอร์ชันเรียกซ้ำ:
find . -type f | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort -u
หากคุณต้องการผลรวม (อาจมีการขยายครั้ง)
find . -type f | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort | uniq -c | sort -rn
ไม่เรียกซ้ำ (โฟลเดอร์เดียว):
for f in *.*; do printf "%s\n" "${f##*.}"; done | sort -u
ฉันเคยใช้โพสต์ฟอรัมนี้เครดิตควรไปที่นั่น
git show --name-only --pretty="" | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort -u
Powershell:
dir -recurse | select-object extension -unique
ขอบคุณhttp://kevin-berridge.blogspot.com/2007/11/windows-powershell.html
.
ในนั้น (เช่นjquery-1.3.4
จะแสดงขึ้นเช่นเดียวกับ.4
ในผลลัพธ์) เปลี่ยนเป็นdir -file -recurse | select-object extension -unique
รับเฉพาะนามสกุลไฟล์
awk-less, sed-less, Perl-less, Python-less POSIX-compliant
find . -type f | rev | cut -d. -f1 | rev | tr '[:upper:]' '[:lower:]' | sort | uniq --count | sort -rn
เคล็ดลับคือมันฝืนเส้นและตัดส่วนขยายที่จุดเริ่มต้น
นอกจากนี้ยังแปลงส่วนขยายเป็นตัวพิมพ์เล็ก
ตัวอย่างผลลัพธ์:
3689 jpg
1036 png
610 mp4
90 webm
90 mkv
57 mov
12 avi
10 txt
3 zip
2 ogv
1 xcf
1 trashinfo
1 sh
1 m4v
1 jpeg
1 ini
1 gqv
1 gcs
1 dv
uniq
ไม่ได้มีธงเต็ม--count
แต่-c
ทำงานได้ดี
ค้นหาทุกจุดด้วยจุดและแสดงเฉพาะคำต่อท้าย
find . -type f -name "*.*" | awk -F. '{print $NF}' | sort -u
ถ้าคุณรู้ว่าคำต่อท้ายทั้งหมดมี 3 ตัวอักษรแล้ว
find . -type f -name "*.???" | awk -F. '{print $NF}' | sort -u
หรือด้วย sed แสดงคำต่อท้ายทั้งหมดที่มีอักขระหนึ่งถึงสี่ตัว เปลี่ยน {1,4} เป็นช่วงของอักขระที่คุณคาดหวังในคำต่อท้าย
find . -type f | sed -n 's/.*\.\(.\{1,4\}\)$/\1/p'| sort -u
-name "."
เพราะนั่นคือสิ่งที่มันมีอยู่แล้ว
การเพิ่มรูปแบบของตัวเองในการผสม ฉันคิดว่ามันง่ายที่สุดของล็อตและมีประโยชน์เมื่อประสิทธิภาพไม่ใช่เรื่องใหญ่
find . -type f | grep -o -E '\.[^\.]+$' | sort -u
$ find . -type f | grep -o -E '\.[^.\/]+$' | sort -u
ใน Python ใช้ generators สำหรับไดเรกทอรีที่มีขนาดใหญ่มากรวมถึงส่วนขยายที่ว่างเปล่าและรับจำนวนครั้งที่ส่วนขยายแต่ละส่วนแสดงขึ้น:
import json
import collections
import itertools
import os
root = '/home/andres'
files = itertools.chain.from_iterable((
files for _,_,files in os.walk(root)
))
counter = collections.Counter(
(os.path.splitext(file_)[1] for file_ in files)
)
print json.dumps(counter, indent=2)
ฉันลองคำตอบมากมายที่นี่แม้แต่คำตอบที่ "ดีที่สุด" พวกเขาทั้งหมดมาจากสิ่งที่ฉันเป็นเฉพาะหลังจาก ดังนั้นนอกเหนือจาก 12 ชั่วโมงที่ผ่านมาในการใช้รหัส regex สำหรับหลาย ๆ โปรแกรมและการอ่านและทดสอบคำตอบเหล่านี้นี่คือสิ่งที่ฉันคิดขึ้นมาซึ่งทำงานได้อย่างที่ฉันต้องการ
find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort -u
หากคุณต้องการจำนวนนามสกุลไฟล์ให้ใช้รหัสด้านล่าง
find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort | uniq -c | sort -rn
ในขณะที่วิธีการเหล่านี้จะใช้เวลาสักครู่จึงจะเสร็จสมบูรณ์และอาจไม่ใช่วิธีที่ดีที่สุดในการแก้ปัญหา แต่ก็ใช้งานได้
อัปเดต: นามสกุลไฟล์ยาว @ @ alpha_989 จะทำให้เกิดปัญหา นั่นเป็นเพราะ regex ดั้งเดิม "[[: alpha:]] {3,6}" ฉันได้อัพเดตคำตอบเพื่อรวม regex "[[: alpha:]] {2,16}" อย่างไรก็ตามทุกคนที่ใช้รหัสนี้ควรทราบว่าตัวเลขเหล่านั้นเป็นจำนวนต่ำสุดและสูงสุดของระยะเวลาที่อนุญาตให้ส่วนขยายสำหรับผลลัพธ์สุดท้าย สิ่งใดก็ตามที่อยู่นอกช่วงนั้นจะถูกแบ่งออกเป็นหลายบรรทัดในเอาต์พุต
หมายเหตุ: โพสต์ดั้งเดิมอ่านแล้ว "- Greps สำหรับนามสกุลไฟล์ระหว่าง 3 และ 6 ตัวอักษร (เพียงปรับตัวเลขหากไม่พอดีกับความต้องการของคุณ) ซึ่งจะช่วยหลีกเลี่ยงไฟล์แคชและไฟล์ระบบ (บิตระบบไฟล์คือการค้นหาคุก) "
แนวคิด: สามารถใช้เพื่อค้นหาไฟล์นามสกุลในระยะเวลาที่กำหนดผ่าน:
find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{4,}" | awk '{print tolower($0)}' | sort -u
โดยที่ 4 คือความยาวของนามสกุลไฟล์ที่จะรวมและจากนั้นค้นหาส่วนขยายที่เกินความยาวนั้น
เนื่องจากมีวิธีแก้ไขปัญหาอื่นซึ่งใช้ Perl:
หากคุณติดตั้ง Python คุณสามารถทำได้ (จากเชลล์):
python -c "import os;e=set();[[e.add(os.path.splitext(f)[-1]) for f in fn]for _,_,fn in os.walk('/home')];print '\n'.join(e)"
ไม่มีคำตอบใด ๆ ที่เกี่ยวข้องกับชื่อไฟล์ที่มีการขึ้นบรรทัดใหม่อย่างถูกต้อง (ยกเว้นของ ChristopheD ซึ่งเพิ่งเข้ามาเมื่อฉันพิมพ์ข้อความนี้) ต่อไปนี้ไม่ใช่เปลือกแบบหนึ่งซับ แต่ทำงานได้และมีความรวดเร็วพอสมควร
import os, sys
def names(roots):
for root in roots:
for a, b, basenames in os.walk(root):
for basename in basenames:
yield basename
sufs = set(os.path.splitext(x)[1] for x in names(sys.argv[1:]))
for suf in sufs:
if suf:
print suf
ฉันไม่คิดว่าอันนี้พูดถึง:
find . -type f -exec sh -c 'echo "${0##*.}"' {} \; | sort | uniq -c
ฉันคิดว่าวิธีที่ง่ายและตรงไปตรงมาที่สุดคือ
for f in *.*; do echo "${f##*.}"; done | sort -u
มันแก้ไขในวิธีที่ 3 ของ ChristopheD
คุณสามารถทำเช่นนี้ได้
find . -type f -name "*.php" -exec PATHTOAPP {} +
ฉันพบว่ามันง่ายและรวดเร็ว ...
# find . -type f -exec basename {} \; | awk -F"." '{print $NF}' > /tmp/outfile.txt
# cat /tmp/outfile.txt | sort | uniq -c| sort -n > tmp/outfile_sorted.txt
คำตอบที่ยอมรับนั้นใช้ REGEX และคุณไม่สามารถสร้างคำสั่ง alias ด้วย REGEX คุณต้องใส่มันลงในเชลล์สคริปต์ฉันใช้ Amazon Linux 2 และทำสิ่งต่อไปนี้:
ฉันใส่รหัสคำตอบที่ยอมรับลงในไฟล์โดยใช้:
sudo เป็นกลุ่ม find.sh
เพิ่มรหัสนี้:
find ./ -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u
บันทึกไฟล์โดยพิมพ์: :wq!
sudo vim ~/.bash_profile
alias getext=". /path/to/your/find.sh"
:wq!
. ~/.bash_profile
.svn
) ให้ใช้find . -type f -path '*/.svn*' -prune -o -print | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u
แหล่งข้อมูล