次のようなファイル名を付けます。
/the/path/foo.txt
bar.txt
私は得ることを願っています:
foo
bar
なぜこれがうまくいかないのですか?
#!/bin/bash
fullfile=$1
fname=$(basename $fullfile)
fbname=${fname%.*}
echo $fbname
それをする正しい方法は何ですか?
外部のbasename
コマンドを呼び出す必要はありません。代わりに、以下のコマンドを使用することができます。
$ s=/the/path/foo.txt
$ echo ${s##*/}
foo.txt
$ s=${s##*/}
$ echo ${s%.txt}
foo
$ echo ${s%.*}
foo
この解決法は最近の( post 2004 ) _ posix _ に準拠したシェル(例:bash
、dash
、ksh
など)でうまくいくはずです。
Bash文字列操作の詳細: http://tldp.org/LDP/LG/issue18/bash.html
basename コマンドには2つの異なる呼び出しがあります。一方ではパスだけを指定します。その場合は最後のコンポーネントになります。もう一方では削除する接尾辞も付けます。そのため、2回目のbasenameの呼び出しを使用することでコード例を単純化できます。また、物事を正しく引用するように注意してください。
fbname = $(ベース名 "$ 1" .txt) echo "$ fbname"
Basenameとcutの組み合わせは、.tar.gz
のようにダブルエンディングの場合でもうまく機能します。
fbname=$(basename "$fullfile" | cut -d. -f1)
この解がBash Parameter Expansionよりも少ない演算能力で済むなら、面白いでしょう。
純粋なbash
、no basename
、no変数ジャグリング。文字列とecho
を設定します。
s=/the/path/foo.txt
echo ${s//+(*\/|.*)}
出力:
foo
注:bash
extglob オプションは "on"にする必要があります(on Ubuntuはデフォルトで "on"です)。
shopt -s extglob
${s//+(*\/|.*)}
を歩く:
${s
- $ sで始まります。//
はパターンのすべてのインスタンスを置き換えます。+(
は、括弧内のパターンリストの1つ以上に一致します。*\/
は、/
より前のものに一致します。 (第1パターン)|
または。 (パターンセパレータ).*
は、.
の後にあるものに一致します。 (第2パターン))
end パターンリスト。}
終了パラメータの拡張 - /
(これは文字列の代わりになるでしょう)がないので、マッチしたパターンは削除されます。関連するman bash
背景:
${parameter/pattern/string} Pattern substitution. The pattern is expanded to produce a pat‐ tern just as in pathname expansion. Parameter is expanded and the longest match of pattern against its value is replaced with string. If pattern begins with /, all matches of pattern are replaced with string. Normally only the first match is replaced. If pattern begins with #, it must match at the begin‐ ning of the expanded value of parameter. If pattern begins with %, it must match at the end of the expanded value of parameter. If string is null, matches of pattern are deleted and the / fol‐ lowing pattern may be omitted. If parameter is @ or *, the sub‐ stitution operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with @ or *, the substitution operation is applied to each member of the array in turn, and the expansion is the resultant list.
If the extglob Shell option is enabled using the shopt builtin, several extended pattern matching operators are recognized. In the following description, a pattern-list is a list of one or more patterns separated by a |. Composite patterns may be formed using one or more of the fol‐ lowing sub-patterns: ?(pattern-list) Matches zero or one occurrence of the given patterns *(pattern-list) Matches zero or more occurrences of the given patterns +(pattern-list) Matches one or more occurrences of the given patterns @(pattern-list) Matches one of the given patterns !(pattern-list) Matches anything except one of the given patterns
ここでは手綱があります:
$(basename ${s%.*})
$(basename ${s} .${s##*.})
Bongbangとw4etwetewtwetが尋ねたのと同じように、これが必要でした。
これは、ファイル名または拡張子を取得するもう1つの(より複雑な)方法です。最初にrev
コマンドを使用してファイルパスを反転し、最初の.
から切り取り、次にファイルパスを再度反転します。
filename=`rev <<< "$1" | cut -d"." -f2- | rev`
fileext=`rev <<< "$1" | cut -d"." -f1 | rev`
もしあなたがWindowsのファイルパス(Cygwinの下で)を使ってNiceをプレイしたいのなら、これも試すことができます。
fname=${fullfile##*[/|\\]}
これは、Windows上でBaSHを使用しているときのバックスラッシュの区切り文字の説明になります。
このスレッドの投稿と、私がよく知っている小さな知識ベースを組み合わせて、拡張機能を抽出するための私の考えた代替案です。
ext="$(rev <<< "$(cut -f "1" -d "." <<< "$(rev <<< "file.docx")")")"
注意:私の引用符の使用について教えてください。それは私のために働いたが、私は彼らの適切な使用法で何かを見逃しているかもしれません(私はおそらく多すぎる)。