Cara mendapatkan hanya nama file menggunakan sed

17

Bagaimana saya bisa mendapatkan hanya nama file menggunakan sed? Saya punya ini

out_file=$(echo $in_file|sed "s/\(.*\.\).*/\1mp4/g")

Tetapi saya juga mendapatkan jalannya /root/video.mp4, dan saya hanya menginginkannya video.mp4.

Shixons
sumber

Jawaban:

26

basenamedari GNU coreutils dapat membantu Anda melakukan pekerjaan ini:

$ basename /root/video.mp4
video.mp4

Jika Anda sudah tahu ekstensi file, Anda dapat memohon basenamemenggunakan sintaks basename NAME [SUFFIX]untuk menghapusnya:

$ basename /root/video.mp4 .mp4
video

Atau opsi lain akan memotong semuanya setelah titik terakhir menggunakan sed:

$ basename /root/video.old.mp4 | sed 's/\.[^.]*$//'
video.old
uloBasEI
sumber
3
Menggunakan sed 's/\.[^.]*$//'seperti yang Anda miliki, akan gagal untuk (tersembunyi) .filenamedan .dan ..direktori
Peter.O
9

Solusi termudah adalah menghapus semuanya sampai tampilan terakhir /:

echo /root/video.mp4 | sed 's/.*\///'

bunga aster
sumber
5

Gunakan salah satu dari cara berikut:

out_file="${in_file##*/}"

out_file="$(basename $in_file)"

out_file="$(echo $in_file | sed 's=.*/==')"

out_file="$(echo $in_file | awk -F"/" '{ print $NF }')"

ps. Anda mendapatkan string yang sama karena dalam pernyataan Anda \(.*\.\)cocok dengan string dari awal hingga titik ( /root/video.) dan kemudian Anda secara manual menambahkan .mp4yang sama dengan di string asli Anda. Anda harus menggunakannya s=.*\([^/]*\)=\1=sebagai gantinya.

Perbarui: (Yang pertama sudah diperbaiki sekarang)

Untuk mendapatkan satu-satunya nama file tanpa ekstensi, Anda dapat:

out_file="$(echo $in_file | sed 's=.*/==;s/\.[^.]*$/.new_ext/')"

out_file="$(echo $in_file | sed 's=\([^/]*\)\.[^./]*$=\1.new_ext=')"

out_file="$(echo $in_file | awk -F"/" '{ gsub (/\.[^/.]*$/,".new_ext",$NF);print $NF }'
buru-buru
sumber
Tetapi dengan salah satu metode itu saya mendapatkan nama file dengan format dan saya hanya perlu mendapatkan nama file dan meletakkan format baru secara manual.
Shixons
Ah, itu masuk akal. Saya telah memperbarui jawaban saya.
buru
@ terburu-buru: Akan ada kasus tepi, misalnya untuk file bernama my.file.tar.gz.
Donasi berhasil pada
@tidak berhasil ada simbol titik yang hilang di yang terakhir seddan awk. Tetap. Terima kasih.
buru
4

Salah satu dasar penggunaan regex adalah bahwa pola pada dasarnya serakah ketika menetapkan wild card. Sementara jawaban yang diajukan oleh @uloBasEI tentu merupakan jawaban yang berfungsi, itu juga membutuhkan penggunaan perintah nama bas. Pertanyaan asli dari @Shixons meminta solusi hanya menggunakan sed.

Sebelum melanjutkan, selalu membantu untuk mengetahui versi sed yang menjadi target. Saya mengasumsikan BSD (seperti yang dikirim dengan OSX).

Pertama-tama, pola yang diajukan dalam pertanyaan awal tidak berfungsi karena ia menangkap semuanya dari awal string input hingga dan termasuk titik terakhir. Tanpa jangkar, pencarian ini akan menelan semuanya dari kiri ke kanan. Karenanya, pola yang cocok "/ 1" adalah segalanya dan termasuk titik terakhir. Bahkan nama file dengan banyak titik akan ditelan utuh. Bukan hasil yang diinginkan sama sekali.

Langkah pertama adalah membangun strategi untuk mengidentifikasi pola. Di sini, Anda ingin menyingkirkan semuanya di sebelah kiri nama file (kami akan membahas ekstensi nanti):

out_file="$(echo $in_file | sed 's/^\(\/.*\/\)*.*/\1/')"

Pencarian cocok dari awal string. Ini cocok dengan pola "/.*" nol kali atau lebih dan menghapus semuanya sesudahnya. Kami mencetak pola yang cocok dengan "\ 1". Kami tidak mencari secara global; kami mencari dari awal string dengan menentukan ^ anchor.

Kami mendapatkan kejelasan yang lebih baik dengan mengaktifkan opsi "-E" sehingga kami tidak harus keluar dari tanda kurung:

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*.*/\1/')"

Jadi sekarang kita memiliki bagian di sebelah kiri. Mari kita tambahkan bagian di sebelah kanan. Perhatikan bahwa kita perlu menjaga bagian kiri sebagai pola karena dengan begitu kita dapat menentukan bahwa itu muncul nol atau lebih. Yang kami lakukan sekarang adalah menambahkan pola untuk bagian di sebelah kanan:

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)/\2/')"

Kami hanya mencetak pertandingan kedua, dengan demikian membuang semuanya kecuali nama file. Tetapi kita masih perlu menghapus ekstensi nama file.

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)\..*$/\2/')"

"$" Di akhir adalah opsional.

Akhirnya, untuk menambahkan ekstensi baru, Anda cukup merevisinya seperti:

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)\..*$/\2.mp4/')"

Optimalisasi tambahan adalah membuat garis miring pertama opsional untuk menangani jalur relatif:

out_file="$(echo $in_file | sed -E 's/^([\/]?.*\/)*(.*)\..*$/\2.mp4/')"

Saya menemukan pertanyaan ini dengan menjadi malas sambil mencari pola sed untuk menggantikan nama bas . Saya sedang mengerjakan sistem yang dilucuti yang tidak memiliki perintah yang diinstal.

markeissler
sumber