web-dev-qa-db-ja.com

シェルスクリプトでファイル名の拡張子を削除するにはどうすればよいですか?

次のコードの何が問題になっていますか?

name='$filename | cut -f1 -d'.''

そのまま、リテラル文字列$filename | cut -f1 -d'.'を取得しますが、引用符を削除しても何も取得しません。入力中

"test.exe" | cut -f1 -d'.'

シェルでは、testという必要な出力が得られます。 $filenameに正しい値が割り当てられていることは既に知っています。私がやりたいのは、拡張子のないファイル名を変数に割り当てることです。

103
mimicocotopus

スクリプト/コマンドでコマンドを実行する場合は、 コマンド置換 構文$(command)を使用する必要があります。

だからあなたのラインは

name=$(echo "$filename" | cut -f 1 -d '.')

コードの説明:

  1. echoは変数$filenameの値を取得し、標準出力に送信します
  2. 次に、出力を取得して、cutコマンドにパイプします
  3. cutはを使用します。文字列をセグメントに分割するためのデリミタ(セパレータとも呼ばれる)として、-fによって、出力に含めるセグメントを選択します
  4. 次に、$()コマンド置換は出力を取得し、その値を返します
  5. 返される値は、nameという名前の変数に割り当てられます

これは、変数の最初の期間.までの部分を与えることに注意してください。

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

パラメーター展開を使用することもできます。

$ filename=foo.txt
$ echo "${filename%.*}"
foo
185
chepner

拡張子がわかっている場合は、 basename を使用できます

$ basename /home/jsmith/base.wiki .wiki
base
90
Steven Penny

ファイル名にドット(拡張子以外)が含まれている場合は、これを使用します。

echo $filename | rev | cut -f 2- -d '.' | rev
15
manish_s
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

好きなものを使用してください。ここでは、最後の.(ドット)の後にテキストが続くと想定しています。

13
Raghwendra

Chepnerの回答のコメントでHawker65が指摘したように、最も投票されたソリューションは、複数の拡張子(filename.tar.gzなど)も、パスの残りのドット(this.path/withなど)も処理しません。 .dots/in.path.name)。可能な解決策は次のとおりです。

a=this.path/with.dots/in.path.name/filename.tar.gz
echo $(dirname $a)/$(basename $a | cut -d. -f1)
1
MadMage

私の推奨はベース名を使用することです。
ubuntuではデフォルトで視覚的にシンプルなコードであり、ほとんどの場合に対応しています。以下は、スペースとマルチドット/サブ拡張子を処理するためのサブケースです。

pathfile = "../ space fld/space -file.tar.gz"

echo $ {pathfile // +(/ |。)}
通常は、最初から拡張子を取り除きます。しかし..パスに失敗しました

echo "$(basename" $ {pathfile%。*} ")"
space -file.tar#私たちはまさにそれが必要だったと思う

重要な注意事項を次に示します。スペースを処理するために、二重引用符の中に二重引用符を使用しました。 $にテキストメッセージを送信するため、一重引用符は渡されません。 Bashは珍しく、展開のために「2番目の「最初の」引用符」を読み取ります。

ただし、.hidden_​​filesについて考える必要があります

hidden = "〜/ .bashrc" echo "$(basename" $ {hidden%。} ")"# "〜"が生成されます!!!
予想された「」結果ではありません。それを実現するには、$ HOMEまたは/ home/user_path /を使用します
再びbashは「異常」であり、「〜」を展開しないため(bash BashPitfallsを検索)
hidden2 = "$ HOME/.bashrc"; echo '$(basename "$ {pathfile%。
}")'

1
Alexey K.
#!/bin/bash
filename=program.c
name=$(basename "$filename" .c)
echo "$name"

出力:

program
0
booboo

コードに関する2つの問題:

  1. 変数に格納する文字列を生成するコマンドを囲むために、 `(バックティック)の代わりに '(ティック)を使用しました。
  2. 変数「$ filename」をパイプに「エコー」して「カット」コマンドに入れませんでした。

コードを「name = `echo $ filename | cut -f 1 -d '。」に変更します`"、以下に示すように(再び、名前変数定義を囲むバックティックに注意してください):

$> filename=foo.txt
$> echo $filename
foo.txt
$> name=`echo $filename | cut -f1 -d'.'`
$> echo $name
foo
$> 
0
FanDeLaU
#!/bin/bash
file=/tmp/foo.bar.gz
echo $file ${file%.*}

出力:

/tmp/foo.bar.gz /tmp/foo.bar

最後の拡張子のみが削除されることに注意してください。

0
C. Paul Bond