Apa yang salah dengan kode berikut?
name='$filename | cut -f1 -d'.''
Sebagaimana adanya, saya mendapatkan string literal $filename | cut -f1 -d'.'
, tetapi jika saya menghapus tanda kutip, saya tidak mendapatkan apa pun. Sementara itu, mengetik
"test.exe" | cut -f1 -d'.'
dalam shell memberi saya output yang saya inginkan , test
. Saya sudah tahu $filename
telah diberi nilai yang benar. Yang ingin saya lakukan adalah menetapkan nama file ke variabel tanpa ekstensi.
basename $filename .exe
akan melakukan hal yang sama. Itu dengan asumsi Anda selalu tahu ekstensi apa yang ingin Anda hapus.basename "$filename" .exe
. Jika tidak, nama file dengan spasi akan menjadi berita buruk.Jawaban:
Anda harus menggunakan sintaks substitusi perintah
$(command)
saat Anda ingin menjalankan perintah dalam skrip / perintah.Jadi baris Anda akan menjadi
name=$(echo "$filename" | cut -f 1 -d '.')
Penjelasan kode:
echo
dapatkan nilai variabel$filename
dan kirimkan ke keluaran standarcut
perintahcut
akan menggunakan. sebagai pembatas (juga dikenal sebagai pemisah) untuk memotong string menjadi segmen dan dengan-f
kita memilih segmen mana yang ingin kita keluaran$()
substitusi perintah akan mendapatkan keluaran dan mengembalikan nilainyaname
Perhatikan bahwa ini memberikan porsi variabel hingga periode pertama
.
:$ filename=hello.world $ echo "$filename" | cut -f 1 -d '.' hello $ filename=hello.hello.hello $ echo "$filename" | cut -f 1 -d '.' hello $ filename=hello $ echo "$filename" | cut -f 1 -d '.' hello
sumber
$()
lebih disukai../ihavenoextension
, seperti jawaban lainnya.Anda juga dapat menggunakan perluasan parameter:
$ filename=foo.txt $ echo "${filename%.*}" foo
Perlu diketahui bahwa jika tidak ada ekstensi file, ekstensi akan mencari titik di belakang, misalnya
.bashrc
) itu akan menghapus seluruh nama file.path.to/myfile
atau./myfile
), maka itu akan memotong di dalam jalur.sumber
echo -n "This.File.Has.Periods.In.It.txt" | awk -F. '{$NF=""; print $0}' | tr ' ' '.' | rev | cut -c 2- | rev
. Terima kasih.image.png.gz
?%.*
hanya akan menghapus ekstensi terakhir; jika Anda ingin menghapus semua ekstensi, gunakan%%.*
.filename=./ihavenoextension
,.Jika Anda mengetahui ekstensinya, Anda dapat menggunakan nama dasar
sumber
.wiki
and end up/home/jsmith/base
?file1=/tmp/main.one.two.sh t=$(basename "$file1") # output is main.one.two.sh name=$(echo "$file1" | sed -e 's/\.[^.]*$//') # output is /tmp/main.one.two name=$(echo "$t" | sed -e 's/\.[^.]*$//') # output is main.one.two
gunakan mana saja yang Anda inginkan. Di sini saya berasumsi bahwa
.
(titik) terakhir yang diikuti oleh teks adalah ekstensi.sumber
file1=/tmp.d/mainonetwosh
? Ekspresi sed harus diganti dengan's/\.[^./]*$//'
Jika nama file Anda berisi titik (selain salah satu ekstensi), gunakan ini:
echo $filename | rev | cut -f 2- -d '.' | rev
sumber
-s
opsi yang diberikancut
, sehingga ia mengembalikan string kosong setiap kali nama file tidak mengandung titik.filename=/tmp.d/foo
:?/
sebagai pembatas.#!/bin/bash file=/tmp/foo.bar.gz echo $file ${file%.*}
keluaran:
Perhatikan bahwa hanya ekstensi terakhir yang dihapus.
sumber
file=/tmp.d/foo
:?Rekomendasi saya adalah menggunakan
basename
.Ini secara default di Ubuntu, kode secara visual sederhana dan menangani sebagian besar kasus.
Berikut adalah beberapa sub-kasus untuk menangani spasi dan multi-titik / sub-ekstensi:
pathfile="../space fld/space -file.tar.gz" echo ${pathfile//+(*\/|.*)}
Biasanya menghilangkan ekstensi dari yang pertama
.
, tetapi gagal di..
jalur kitaecho **"$(basename "${pathfile%.*}")"** space -file.tar # I believe we needed exatly that
Ini catatan penting:
Namun, Anda tetap perlu memikirkannya
.hidden_files
hidden="~/.bashrc" echo "$(basename "${hidden%.*}")" # will produce "~" !!!
bukan hasil yang "" diharapkan. Untuk mewujudkannya gunakan
$HOME
atau/home/user_path/
karena sekali lagi bash "tidak biasa" dan jangan perluas "~" (cari bash BashPitfalls)
hidden2="$HOME/.bashrc" ; echo '$(basename "${pathfile%.*}")'
sumber
Hanya menggunakan built-in POSIX:
#!/usr/bin/env sh path=this.path/with.dots/in.path.name/filename.tar.gz # Get the basedir without external command # by stripping out shortest trailing match of / followed by anything dirname=${path%/*} # Get the basename without external command # by stripping out longest leading match of anything followed by / basename=${path##*/} # Strip uptmost trailing extension only # by stripping out shortest trailing match of dot followed by anything oneextless=${basename%.*}; echo "$noext" # Strip all extensions # by stripping out longest trailing match of dot followed by anything noext=${basename%%.*}; echo "$noext" # Printout demo printf %s\\n "$path" "$dirname" "$basename" "$oneextless" "$noext"
Demo cetakan:
sumber
#!/bin/bash filename=program.c name=$(basename "$filename" .c) echo "$name"
keluaran:
sumber
Seperti yang ditunjukkan oleh Hawker65 dalam komentar jawaban chepner, solusi yang paling banyak dipilih tidak menangani beberapa ekstensi (seperti namafile.tar.gz), atau titik-titik di jalur lainnya (seperti this.path / with .dots / in.path.name). Solusi yang mungkin adalah:
a=this.path/with.dots/in.path.name/filename.tar.gz echo $(dirname $a)/$(basename $a | cut -d. -f1)
sumber
.tar.gz
, Anda bisa menggunakan$(basename "$a" .tar.gz)
. Selain itu, pastikan untuk membungkus variabel Anda dalam tanda kutip di mana-mana jika ada kemungkinan variabel itu akan berisi spasi atau karakter aneh lainnya!Dua masalah dengan kode Anda:
Saya akan mengubah kode Anda menjadi "name = ʻecho $ filename | cut -f 1 -d '.' `", seperti yang ditunjukkan di bawah ini (sekali lagi, perhatikan tanda centang di sekitar definisi variabel nama):
$> filename=foo.txt $> echo $filename foo.txt $> name=`echo $filename | cut -f1 -d'.'` $> echo $name foo $>
sumber
Jawaban yang diberikan sebelumnya memiliki masalah dengan jalur yang berisi titik. Beberapa contoh:
Saya lebih suka menggunakan
|sed -e 's/\.[^./]*$//'
. Sebagai contoh:$ echo "/xyz.dir/file.ext" | sed -e 's/\.[^./]*$//' /xyz.dir/file $ echo "./file.ext" | sed -e 's/\.[^./]*$//' ./file $ echo "/a.b.c/x.ddd.txt" | sed -e 's/\.[^./]*$//' /a.b.c/x.ddd
Catatan: Jika Anda ingin menghapus beberapa ekstensi (seperti pada contoh terakhir), gunakan
|sed -e 's/\.[^/]*$//'
:$ echo "/a.b.c/x.ddd.txt" | sed -e 's/\.[^/]*$//' /a.b.c/x
Namun, metode ini akan gagal di "dot-files" tanpa ekstensi:
$ echo "/a.b.c/.profile" | sed -e 's/\.[^./]*$//' /a.b.c/
Untuk menutupi juga kasus seperti itu, Anda dapat menggunakan:
$ echo "/a.b.c/.profile" | sed -re 's/(^.*[^/])\.[^./]*$/\1/' /a.b.c/.profile
sumber