วิธีการส่งออกเฉพาะชื่อไฟล์ (มีช่องว่าง) ใน ls -Al?


78

ฉันควร echo เฉพาะชื่อของไฟล์หรือไดเรกทอรีที่มีโครงสร้างนี้:

ls -Al | while read string
do
...
done

ls -Al ผลลัพธ์:

drwxr-xr-x  12 s162103  studs         12 march 28 12:49 personal domain
drwxr-xr-x   2 s162103  studs          3 march 28 22:32 public_html
drwxr-xr-x   7 s162103  studs          8 march 28 13:59 WebApplication1

เช่นถ้าฉันลอง:

ls -Al | while read string
do
echo "$string" | awk '{print $9}
done

จากนั้นให้ส่งออกเฉพาะไฟล์และไดเรกทอรีที่ไม่มีช่องว่าง หากไฟล์หรือไดเรกทอรีมีช่องว่างเช่น "โดเมนส่วนบุคคล" มันจะเป็นเพียงคำว่า "ส่วนบุคคล"

ฉันต้องการทางออกที่ง่ายมาก อาจมีทางออกที่ดีกว่า awk


2
ทำไมไม่เพียงls -Al *' '*? lsผลลัพธ์ของการแยกวิเคราะห์ไม่เคยนำไปสู่สิ่งที่ดี
จัดการ

1
หากคุณต้องการสิ่งที่จะทำงานในระวัง * ใด ๆ ls -Al | whileที่พยายามหลีกเลี่ยงการใช้ for string in *; do echo "$string"; doneวิธีที่ง่ายและน่าเชื่อถือมากขึ้นคือ
forcefsck

ต้องการเพียงแค่การก่อสร้างนี้ .. โอเคไม่ใช่เรื่องง่ายวิธีแก้ปัญหาใด ๆ !
Alex Zern

1
ทำไมคุณต้อง ls ? การแยกวิเคราะห์lsและ "ทำงานในทุก * ระวังและจะไม่แตกถ้ามีอะไรเกิดขึ้น" ไม่ไปด้วยกันได้ดี
terdon

คำตอบ:


97

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

ดี...

find ./  -printf "%f\n"

หรือ

for n in *; do printf '%s\n' "$n"; done

... เลว ...

หากคุณต้องการใช้งานจริงๆlsคุณสามารถทำให้มันแข็งแกร่งขึ้นเล็กน้อยโดยทำสิ่งนี้:

ls -lA | awk -F':[0-9]* ' '/:/{print $2}'

... และสิ่งที่น่าเกลียด

หากคุณยืนยันในการทำผิดวิธีอันตรายและเพียงแค่ต้องใช้whileวนทำเช่นนี้:

ls -Al | while IFS= read -r string; do echo "$string" | 
    awk -F':[0-9]* ' '/:/{print $2}'; done

แม้ว่าอย่างจริงจังแค่ทำไม่ได้


drwx------ 2 s162103 studs 3 oct. 9 2012 .ssh drwxr-xr-x 3 s162103 studs 6 oct. 25 09:02 .subversion drwxrwxrwt 3 s162103 studs 3 nov. 15 2012 .TempoItemsบางครั้งฉันมีวันที่ไม่มีเวลามีเพียงปีและเพ่งมองที่ว่างเปล่า
Alex Zern

1
@AlexZern lsดีว่าเป็นหนึ่งในเหตุผลที่คุณไม่ได้แยกการส่งออกของ
terdon

2
@AlexZern ทำไมคุณถึงต้องการ-lสวิตช์ล่ะ? ls -Aหากสิ่งที่คุณต้องการคือชื่อไฟล์ที่เรียกใช้เพียง การใช้-lแค่ทำให้ชีวิตของคุณหนักขึ้นเพราะตอนนี้คุณต้องแยกวิเคราะห์ผลลัพธ์
terdon

เพราะฉันต้องการข้อมูลเพิ่มเติมเช่นการเข้าถึงวันที่เจ้าของ ฯลฯ และฉันเขียนสคริปต์ขนาดใหญ่ซึ่งทำงานได้ดียกเว้นไฟล์พิมพ์และชื่อ dir ที่มีช่องว่าง
Alex Zern

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

74

มีเหตุผลที่ls -A1* จะไม่ทำงานไหม?

เช่น:

$ touch file1 file2 file\ with\ spaces
$ ls -Al
total 0
-rw-r--r-- 1 bahamat bahamat 0 Mar 30 22:31 file1
-rw-r--r-- 1 bahamat bahamat 0 Mar 30 22:31 file2
-rw-r--r-- 1 bahamat bahamat 0 Mar 30 22:31 file with spaces
$ ls -A1
file1
file2
file with spaces
$

* หมายเหตุ: นั่นคือตัวอักษร A และหมายเลขหนึ่ง


4
-1 คืออัจฉริยะ ฉันไม่รู้ว่ามันว่าง (ฉันรู้ว่าฉันรู้แล้ว RTFM)
The Lazy Coder

ใช้งานได้กับไดเรกทอรีปัจจุบันเท่านั้นหากคุณต้องการแสดงรายชื่อไฟล์จากไดเรกทอรีอื่นพูดว่า ~ / projects จากนั้นคุณจะได้รับเส้นทางแบบเต็มแทนชื่อไฟล์
thecotne

@thecotne บน Mac 10.9.5 เป็นเพียงรายชื่อไฟล์ คุณใช้ระบบปฏิบัติการอะไร?
AJP

ฉันใช้ ls นี้ / โครงการ / *. ประเสริฐโครงการ -A1 สำหรับ ls ~ / โครงการ -A1 ฉันได้รับชื่อเท่านั้น
thecotne

3
@TheLazyCoder ไม่คาดว่าจะอ่านคู่มือ
c24w

41

ฉันสงสัยว่าทำไมไม่มีใครพูดถึงคำสั่งง่ายๆนี้:

ls -a | sort

2
ยอดเยี่ยม! ความคิดใด ๆ ที่sortทำให้piping เป็นสาเหตุให้บล็อกหลายคอลัมน์ไม่ถูกตรึงในคอลัมน์เดียว
msciwoj

@msciwoj มันใช้เวลาแค่สตริงใด ๆ คั่นด้วย whitespaces และพิมพ์พวกเขาเรียงลำดับคั่นด้วย endlines
Ben

ที่สมบูรณ์แบบ! ทำไมคนนี้ไม่ถูกทำเครื่องหมายว่าเป็นคำตอบที่แท้จริง!
夏期劇場

3
มันทำงานที่นี่เพราะlsย้อนกลับไปls -1(output columnd เดี่ยว) เมื่อผลผลิตของตนไม่ได้ไปไปยังสถานี (และปิดการใช้ตัวอักษรที่ไม่สามารถพิมพ์ข้อความ / ทดแทน @Kusalananda ของคุณlsจะไม่ได้ตาม POSIX หากยังคงไม่) lsเอาต์พุตถูกเรียงลำดับแล้ว ดังนั้นการวางท่อให้อย่างsortดีที่สุดจะไม่ทำอะไรเลยและยิ่งแย่ลงทำให้เอาต์พุตแย่ลง (หากชื่อไฟล์มีอักขระขึ้นบรรทัดใหม่) หรือล้มเหลวสำหรับชื่อไฟล์ที่ไม่ใช่ข้อความ ls -a | catจะดีกว่า หรือดียิ่งขึ้นls -A1ดังที่ได้กล่าวไปแล้ว (และเนื่องจากโดยทั่วไปคุณต้องการเปลี่ยน / อ้างอิงเมื่อแสดงบนเครื่องปลายทาง)
Stéphane Chazelas

1
@ StéphaneChazelasตั้งข้อสังเกต lsทำงานแตกต่างกันเมื่อเอาต์พุตไม่ใช่เทอร์มินัล
Kusalananda

3

คุณไม่สามารถแยกเอาท์พุทของlsให้อย่างเดียวls -lเพราะขึ้นบรรทัดใหม่เช่นเดียวกับช่องว่างเป็นตัวอักษรที่ถูกต้องเช่นเดียวกับในชื่อไฟล์ นอกจากนี้คุณจะต้องพิจารณา symlinks ... foo -> barที่มีเอาท์พุทเช่น

ทำไมคุณถึงใช้-lถ้าคุณต้องการชื่อไฟล์เท่านั้น

แค่ทำ:

for file in *; do
  ...
done

หากคุณต้องการรวมไฟล์ dot (ยกเว้น.และ..) ขึ้นอยู่กับเชลล์:

zsh:

for file in *(ND); do
  ...
done

bash:

shopt -s nullglob dotglob
for file in *; do
  ...
done

ksh93:

FIGNORE='@(.|..)'
for file in ~(N)*; do
  ...
done

POSIXly:

for file in .[!.]* ..?* *; do
  [ -e "$file" ] || [ -L "$file" ] || continue
  ...
done


1
ls -Al | tr -s ' ' | cut -f9- -d' '

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


1

ลอง ( bash, zsh, ksh93ไวยากรณ์):

find . -type f -print0 | while IFS= read -r -d '' filename; do
  ...
done

สิ่งนี้จะเรียกซ้ำและแสดงเฉพาะไฟล์ปกติ (เช่นไม่มี dirs หรือ symlink / fifos / อุปกรณ์ ... )

ดูสิ่งนี้ด้วย:



-1
ls --file *|grep ^ 

มันจะแสดงไฟล์อะไรภายใต้ไดเรกทอรีใด


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