sedを使用してファイル名のみを取得する方法


17

sedを使用してファイル名のみを取得するにはどうすればよいですか?私はこれを持っています

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

しかし、私もパスを取得し、/root/video.mp4私だけが欲しいvideo.mp4

回答:


26

basenameGNU coreutilsからこの仕事をするのを助けることができます:

$ basename /root/video.mp4
video.mp4

ファイルの拡張子がすでにわかっている場合はbasename、構文を使用して呼び出してbasename NAME [SUFFIX]削除できます。

$ basename /root/video.mp4 .mp4
video

または、次のオプションを使用して、最後のドットの後にすべてをカットしますsed

$ basename /root/video.old.mp4 | sed 's/\.[^.]*$//'
video.old

3
使用してsed 's/\.[^.]*$//'、あなたが持っているように、(隠された)のために失敗する.filename...ディレクトリ
Peter.O

9

最も簡単な解決策は、最後に現れるまですべてを削除することです/

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


5

次のいずれかの方法を使用します。

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 }')"

追伸 ステートメントで\(.*\.\)、最初からドット(/root/video.)までの文字列と一致するため、同じ文字列を取得し、元の文字列と同じ文字列を手動で追加.mp4します。s=.*\([^/]*\)=\1=代わりに使用する必要があります。

更新:(最初の問題は修正されました)

拡張子のない唯一のファイル名を取得するには:

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 }'

しかし、これらのメソッドのいずれかを使用して、ファイル名をフォーマットで取得し、ファイル名のみを取得して新しいフォーマットを手動で配置する必要があります。
シクソン

ああ、それは理にかなっています。回答を更新しました。
ラッシュ

@rush:などの名前のファイルの場合など、エッジケースがありますmy.file.tar.gz
-donothing正常に

@donothingは、最後のsedとにドット記号がありませんでしたawk。修繕。ありがとうございました。
ラッシュ

4

正規表現を使用する基本の1つは、ワイルドカードを指定するときにパターンが本質的に貪欲であることです。@uloBasEIによって提案された答えは確かに有効な答えですが、basenameコマンドの使用も必要です。@Shixonsからの元の質問は、sedのみを使用したソリューションを要求しています。

続行する前に、sedのどのバージョンがターゲットであるかを知ることは常に役立ちます。BSD(OSXに付属)を想定しています。

まず第一に、元の質問で提案されたパターンは、入力文字列の最初から最後のドットを含むすべてをキャプチャするため、機能しません。アンカーがなければ、この検索はすべてを左から右に飲み込みます。したがって、「/ 1」に一致するパターンは、最後のドットまでのすべてです。複数のドットを含むファイル名でも全体が飲み込まれます。望ましい結果ではありません。

最初のステップは、パターンを識別するための戦略を確立することです。ここでは、ファイル名の左側にあるすべてのものを削除します(拡張子については後で説明します)。

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

検索は、文字列の先頭から一致します。「/.*」のパターンに0回以上一致し、その後すべてを削除します。一致したパターンを「\ 1」で印刷します。私たちはグローバルに検索していません。^アンカーを指定して、文字列の先頭から検索しています。

「-E」オプションを有効にすることでより明確になり、括弧をエスケープする必要がなくなります。

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

これで、左側に部品ができました。右側に部品を追加しましょう。左の部分をパターンとして保持する必要があることに注意してください。これにより、左の部分を0回以上表示するように指定できます。ここで行うことは、右側のパーツのパターンを追加することだけです。

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

2番目の一致のみを出力するため、ファイル名以外はすべて破棄されます。ただし、ファイル名拡張子を削除する必要があります。

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

末尾の「$」はオプションです。

最後に、新しい拡張機能を追加するには、次のように修正します。

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

追加の最適化は、相対パスを処理するために最初のスラッシュをオプションにすることです。

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

basenameを置き換えるsedパターンを探している間に怠beingであるということで、私はこの質問に出会いました。そのコマンドがインストールされていないストリップされたシステムで作業しています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.