Saya mencari satu-liner elegan (misalnya, awk
) yang akan mempersingkat string jalur Unix menggunakan karakter pertama dari setiap orang tua / tingkat menengah, tetapi nama lengkap penuh. Lebih mudah ditunjukkan dengan contoh:
/path/to/file
→/p/t/file
/tmp
→/tmp
/foo/bar/.config/wizard_magic
→/f/b/./wizard_magic
/foo/bar/.config/wizard_magic
→/f/b/.c/wizard_magic
Mengingat poin-poin bagus oleh @ MichaelKjörling dan @ChrisH di bawah, contoh ini menunjukkan bagaimana kita dapat menampilkan dua karakter pertama ketika karakter pertama adalah sebuah titik.
/f/b/.c/wizard_magic
. Titik sering sangat umum dalam direktori tertentu untuk menjadi petunjuk yang sangat kecil ke tempat Anda harus mencari..
biasanya hanya berarti "direktori saat ini". Jadi/f/b/./wizard_magic
sama dengan/f/b/wizard_magic
karena elemen path./
dikompres ke elemen path kosong.Jawaban:
Untuk file uji ini:
Singkatan dapat dihasilkan dengan kode awk ini:
Sunting1: Menggunakan dua karakter untuk nama-titik
Versi ini menyingkat nama direktori menjadi satu karakter kecuali untuk nama yang dimulai dengan
.
yang disingkat menjadi dua karakter:Bagaimana itu bekerja
-F/
Ini memberitahu awk untuk menggunakan garis miring sebagai pemisah bidang pada input.
for (i=1;i<NF;i++) $i=substr($i,1,1)
Ini melingkupi setiap bidang, kecuali yang terakhir, dan menggantinya hanya dengan karakter pertamanya.
EDIT1: Dalam versi revisi, kami membuat panjang substring 2 ketika bidang dimulai
.
.1
Ini memberitahu awk untuk mencetak baris yang direvisi.
OFS=/
Ini memberitahu awk untuk menggunakan garis miring sebagai pemisah bidang pada keluaran.
sumber
‥
pemisah:awk -F/ '{for (i=1;i<NF;i++) $i=substr($i,1,1+($i~/^[.]/))(i==1||length($i)<2?"":"‥")} 1' OFS=/ <<<$PWD
memberikan:/foo/bar/.config/wizard_magic
→/f‥/b‥/.c‥/wizard_magic
Cukup mudah di sed (dengan asumsi tidak ada baris baru dalam nama file):
Kurang mudah dalam awk karena tidak memiliki referensi kembali (kecuali dalam Gawk, tetapi dengan sintaks yang canggung):
Di zsh (dengan jalur di
$full_path
):sumber
\1
dalam string pengganti tidak berarti referensi ke grup tangkapan dalam pola. Backreference adalah backreference di mana pun Anda menggunakannya.Anda dapat melakukannya seperti:
dan inilah
sed
:yang cukup dekat untuk melakukan semua hal yang sama fungsi tidak di bawah ini. itu tidak menyingkat dengan tildes atau memasukkan
$PWD
ke kepala untuk non-slash terkemuka seperti fungsinya (dan pada kenyataannya, tidak pernah mencetak slash utama) tetapi itu bisa ditangani sesudahnya. itu memproses komponen jalur nol, dan titik tunggal, dan menyingkirkan..
kasus.diberi
man
jalur yang sama seperti dicd
atas yang dicetak:itu juga akan mencetak satu atau dua titik utama tambahan untuk setiap komponen jalur yang dimulai dengan itu dan bukan hanya satu atau dua titik.
Anda bertanya tentang melakukan lebih dari satu karakter untuk path-komponen yang dimulai dengan a
.
. untuk melakukannya saya pikir setiap komponen akan memerlukan perhatian individu, dan karena saya ingin tahu, saya mencoba tangan saya untuk membuat jalur kanonik tanpa direktori perubahan. setelah beberapa trial-and-error saya akhirnya memutuskan satu-satunya cara untuk melakukannya dengan benar adalah melakukannya dua kali - mundur dan maju:sehingga tidak pernah mengubah direktori atau mencoba mengonfirmasi keberadaan komponen jalur apa pun, tetapi meremas
/
pembatas berulang dan menjatuhkan/./
komponen titik tunggal sepenuhnya, dan memproses/../
komponen titik ganda secara tepat.ketika
$IFS
diatur ke beberapa karakter non-spasi , urutan dua atau lebih$IFS
karakter akan menghasilkan satu atau lebih bidang nol. jadi beberapa tebasan berurutan berhasil pada argumen bernilai nol. hal yang sama berlaku untuk$IFS
tokoh utama . dan ketikaset -- $1
terbelah, jika hasilnya$1
nol maka dimulai dengan garis miring,${1:+$PWD}
jika tidak, maka saya masukkan$PWD
. dengan kata lain, jika argumen pertama tidak dimulai dengan garis miring, itu akan$PWD
dipertanyakan. itu sedekat ini dengan validasi jalur .jika tidak,
for
loop pertama secara terbalik membalikkan urutan komponen path, seperti:... saat melakukan itu mengabaikan komponen titik-tunggal atau nol, dan untuk
..
itu tidak ...... pass kedua membalikkan efek ini, dan saat melakukannya ia memeras setiap komponen menjadi 2-titik + char , atau 1-titik + char , atau char .
jadi itu harus bekerja ke jalur kanonik terlepas dari keberadaannya.
saya menambahkan / mengurangi sedikit ke loop kedua. sekarang
set
lebih jarang (hanya sekali untuk setiap[!./]*
komponen) , dancase
evaluasi pola hubung singkat sebagian besar waktu (berkat pola yang disebutkan di atas) , dan termasuk evaluasi kecocokan ekor-panggilan terhadap~
. jika semua atau bagian terdepan (sebagaimana dibagi pada seluruh komponen) dari jalur kanonik akhirnya dapat cocok~
, bit yang cocok akan dilepas dan literal~
akan diganti. untuk melakukan ini, saya harus memelihara salinan lengkap dari path disamping yang disingkat juga (karena mencocokkan path yang disingkat dengan~
mungkin tidak akan sangat membantu) , dan ini disimpan$3
. yang terakhirwhile
cabang loop hanya dijalankan jika~
dicocokkan sebagai subset dari$3
.jika Anda menjalankannya dengan
set -x
jejak diaktifkan, Anda dapat melihatnya bekerja.sumber
Tema "mencurigakan" Zsh dari Oh My Zsh berisi cuplikan Perl untuk melakukan hal yang memiliki dukungan Unicode:
sumber
Apakah Anda ingin memiliki nama pendek atau menggunakannya untuk commandline Anda?
Untuk baris perintah, saya memiliki saran berikut:
Tidak menyelesaikan file di shell Anda membantu Anda?
Terkadang Anda beruntung dan tidak harus melakukan sesuatu yang istimewa:
Ketika Anda hanya memiliki beberapa direktori yang Anda minati, Anda dapat menggunakan alias:
Atau Anda dapat mengatur variabel untuk direktori favorit Anda
Saya pikir opsi ini lebih masuk akal daripada mencoba menyelesaikan ini dengan fungsi yang didefinisikan dalam .bashrc (atau .profile) seperti
dan memanggil fungsi ini x dengan spasi di antara huruf-huruf Anda:
sumber