214

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

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

そのまま、リテラル string を取得します$filename | cut -f1 -d'.'が、引用符を削除すると何も取得されません。その間、タイピング

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

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

4

15 に答える 15

393

パラメータ展開も使用できます。

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

ファイル拡張子がない場合は、ドットをさらにさかのぼって検索することに注意してください。

  • ファイル名がドットのみで始まる場合 (例: .bashrc)、ファイル名全体が削除されます。
  • パスのみにドットがある場合 (例:path.to/myfileまたは./myfile)、パス内でトリムされます。
于 2012-08-28T04:55:25.567 に答える
167

スクリプト/コマンドでコマンドを実行する場合は、コマンド置換構文を使用する必要があります。$(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
于 2012-08-28T04:10:56.783 に答える
159

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

$ basename /home/jsmith/base.wiki .wiki
base
于 2015-05-02T21:49:17.730 に答える
21

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

# 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"

印刷デモ:

this.path/with.dots/in.path.name/filename.tar.gz
this.path/with.dots/in.path.name
filename.tar.gz
filename.tar
filename
于 2020-09-19T15:37:11.323 に答える
3

私のお勧めは、 を使用することbasenameです。
Ubuntu ではデフォルトで、視覚的に単純なコードであり、ほとんどのケースに対処します。

スペースとマルチドット/サブエクステンションを処理するサブケースを次に示します。

pathfile="../space fld/space -file.tar.gz"
echo ${pathfile//+(*\/|.*)}

通常は first から拡張子を取り除きますが、私たちのパス.では失敗します..

echo **"$(basename "${pathfile%.*}")"**  
space -file.tar     # I believe we needed exatly that

重要な注意事項を次に示します。

スペースを処理するために、二重引用符内に二重引用符を使用しました。$ をテキスト送信するため、一重引用符は渡されません。Bash は異常で、展開により「2 番目の "最初の" 引用符」を読み取ります。

ただし、まだ考える必要があります.hidden_files

hidden="~/.bashrc"
echo "$(basename "${hidden%.*}")"  # will produce "~" !!!  

期待される "" 結果ではありません。それを実現するには$HOME、または/home/user_path/
再びbashが「珍しい」ため、「〜」を展開しないでください(bash BashPitfallsを検索してください)

hidden2="$HOME/.bashrc" ;  echo '$(basename "${pathfile%.*}")'
于 2019-03-06T07:55:58.943 に答える
0

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

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

コードを「name=`echo $filename | cut -f 1 -d '.」に変更します。`"、以下に示すように (再度、name 変数定義を囲む後ろの目盛りに注意してください):

$> filename=foo.txt
$> echo $filename
foo.txt
$> name=`echo $filename | cut -f1 -d'.'`
$> echo $name
foo
$> 
于 2016-07-28T00:10:32.403 に答える