Bagaimana cara menghasilkan hanya nama file (dengan spasi) di ls -Al?

80

Saya harus menggemakan hanya nama file atau direktori dengan konstruksi ini:

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

ls -Al keluaran:

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

Sebagai contoh jika saya mencoba:

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

kemudian hanya output file dan direktori tanpa spasi. Jika file atau direktori memiliki ruang seperti "domain pribadi" itu hanya akan menjadi kata "pribadi".

Saya butuh solusi yang sangat sederhana. Mungkin ada solusi yang lebih baik daripada awk.

Alex Zern
sumber
2
Kenapa tidak adil ls -Al *' '*? lsHasil parsing tidak pernah menghasilkan sesuatu yang baik.
manatwork
1
Jika Anda membutuhkan sesuatu yang akan berfungsi di * nix apa pun coba hindari menggunakan ls -Al | while. Cara yang sederhana dan lebih dapat diandalkan adalah for string in *; do echo "$string"; done.
forcefsck
hanya perlu dengan konstruksi ini .. mungkin, tidak sederhana, ada solusi!
Alex Zern
1
Mengapa Anda butuhkan ls ? Parsing lsdan "bekerja di semua * nix dan tidak akan pecah jika sesuatu terjadi" tidak berjalan dengan baik.
terdon

Jawaban:

99

Anda seharusnya tidak melewatkan output darils . Jika ini adalah pekerjaan rumah dan Anda harus, profesor Anda tidak tahu apa yang mereka bicarakan. Mengapa Anda tidak melakukan hal seperti ini:

Yang baik...

find ./  -printf "%f\n"

atau

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

...keburukan...

Jika Anda benar-benar ingin menggunakannya ls, Anda bisa membuatnya sedikit lebih kuat dengan melakukan sesuatu seperti ini:

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

... dan yang jelek

Jika Anda bersikeras melakukannya dengan cara yang salah, berbahaya, dan hanya perlu menggunakan whileloop, lakukan ini:

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

Serius, tapi jangan.

terdon
sumber
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 .TempoItemskadang-kadang saya dapat kencan tanpa waktu, hanya setahun dan gawk kembali kosong
Alex Zern
1
@AlexZern Nah, itulah salah satu alasan Anda tidak menguraikan output ls.
terdon
2
@ AlexZern mengapa Anda tetap memerlukan -lsaklar? Jika semua yang Anda inginkan adalah nama file, jalankan saja ls -A. Menggunakan -lhanya membuat hidup Anda lebih sulit karena Anda sekarang harus mengurai hasilnya.
terdon
karena saya memerlukan informasi tambahan seperti akses, tanggal, pemilik, dll. Dan saya menulis skrip besar, yang berfungsi dengan baik, kecuali mencetak file dan nama dir dengan spasi.
Alex Zern
3
Baiklah kalau begitu. Apa yang kita miliki di sini adalah masalah XY . lsbukan cara terbaik untuk mendapatkan apa yang Anda butuhkan. Mengapa Anda tidak memposting pertanyaan baru yang menjelaskan informasi yang ingin Anda kumpulkan dan kami dapat menyarankan cara untuk melakukannya. Atau, Anda dapat menggunakan skrip Anda apa adanya, dan menggunakan salah satu saran di atas untuk mencetak nama saja. Tapi serius, jangan parse ls, katakan saja apa yang Anda coba lakukan pada pertanyaan baru.
terdon
74

Apakah ada alasan bahwa ls -A1* tidak akan berfungsi?

Misalnya:

$ 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
$

* Catatan: itu huruf kapital A dan nomor satu.

bahamat
sumber
4
-1 adalah genius. Saya tidak tahu itu tersedia. (Saya tahu saya tahu. RTFM)
The Lazy Coder
yang hanya berfungsi untuk direktori saat ini jika Anda ingin membuat daftar nama file dari direktori lain katakan ~ / proyek maka Anda akan mendapatkan path lengkap alih-alih nama file
thecotne
@thecotne pada Mac 10.9.5 hanya mencantumkan nama file. OS apa yang Anda gunakan?
AJP
saya menjalankan ini ls ~ / proyek / * .sublim-proyek -A1 untuk ls ~ / proyek -A1 saya hanya mendapatkan nama
thecotne
3
@TheLazyCoder tidak diharapkan membaca manual.
c24w
41

Saya heran mengapa tidak ada yang menyebutkan perintah sederhana ini:

ls -a | sort
Ben
sumber
2
Cemerlang! sortAdakah ide bagaimana perpipaan menyebabkan blok multi-kolom menjadi tidak diproteksi menjadi satu kolom?
msciwoj
@msciwoj hanya membutuhkan string yang dipisahkan oleh spasi putih dan mencetaknya diurutkan dipisahkan oleh endline
Ben
SEMPURNA! Kenapa yang ini tidak ditandai sebagai jawaban yang asli !?
夏 期 劇場
3
Ini bekerja di sini karena lskembali ke ls -1(output columnd tunggal) ketika outputnya tidak pergi ke terminal (dan menonaktifkan kutipan / penggantian karakter yang tidak dapat dicetak; @ Kusalananda, Anda lstidak mematuhi POSIX jika masih melakukannya). lsoutput sudah diurutkan. Jadi perpipaan untuk yang sortterbaik tidak akan melakukan apa-apa, dan lebih buruk lagi memotong-motong output (jika nama file berisi karakter baris baru) atau gagal untuk nama file yang bukan teks. ls -a | catakan lebih baik. Atau bahkan lebih baik ls -A1seperti yang telah disebutkan (dan karena Anda biasanya ingin penggantian / penawaran ketika ditampilkan pada terminal)
Stéphane Chazelas
1
@ StéphaneChazelas Tercatat lsberperilaku berbeda ketika output bukan terminal.
Kusalananda
3

Anda tidak dapat mem-parsing keluaran ls, apalagi ls -lkarena baris baru, sama seperti spasi karakter yang valid dalam nama file. Selain itu, Anda harus mempertimbangkan symlink yang memiliki output seperti ... foo -> bar.

Mengapa Anda -ltetap menggunakan jika Anda hanya ingin nama file?

Kerjakan saja:

for file in *; do
  ...
done

Jika Anda ingin memasukkan file dot (kecuali .dan ..), tergantung pada shell:

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
Stéphane Chazelas
sumber
1

Bagaimana tentang:

for file in * .[!.]*
do
  printf "%s\n" "$file"
done
Pengamat
sumber
1
ls -Al | tr -s ' ' | cut -f9- -d' '

kompres beberapa spasi menjadi spasi tunggal dengan tr maka Anda dapat menggunakan cut untuk membagi bidang

pengguna sederhana
sumber
-1
ls --file *|grep ^ 

ini menampilkan file apa di bawah direktori apa.

vars
sumber
Saya tidak berpikir bahwa ini menjawab pertanyaan.
Jeff Schaller