シェル変数はパスを保持します。ファイル名部分をどのように取得できますか?
bash(1)で、私は実験を通して環境変数の名前が."${i/*\///}"
どこにあるかを介して実行できることを発見しました。i
このアプローチは醜いだけでなく、/
パスに文字が含まれていない場合でも間違っています。
そのような機能が必要な実際のケースを紹介します。ソースディレクトリ内の各PDFファイルに対して現在のディレクトリへのシンボリックリンクを作成するとします。
$ for i in /source/path/*.pdf; do\
ln -s "$i" ."${i/*\///}"; \
done
答え1
${i##*/}
bash
これは、、dash
などをksh
含むPosixシェルに適用されます。zsh
標準からPOSIXパラメータ拡張セクションPosixシェルとユーティリティの仕様:
${パラメータ##[単語]}
最大プレフィックスパターンを削除します。パターンを生成するには、単語を拡張する必要があります。次に、パラメータ拡張によって、プレフィックスの最大部分が削除されたパターンと一致するパラメータを生成する必要があります。
あるいは、伝統的にbasename
この目的のためにコマンドが使用されていました。 警告する:basename
外部コマンド(例:)で実装されているため、パフォーマンスが重要な問題になる可能性があります/usr/bin/basename
。ループ内でこれを行うので、各ファイルに対して外部コマンドを呼び出します。 1000ファイルのリストの場合、これはbasename
0.05秒(パラメータ拡張)と2.0秒(コマンド)の差になる可能性があります。ただし、10,000個のファイルリストの場合、これは0.5秒(拡張)と20秒()の差がありますbasename
。ファイルの数が増えるほど、パフォーマンスの違いはより深刻になります。
読みやすさとパフォーマンスのために、次の独自の機能を実装できますbasename
。
mybasename() { echo "${1##*/}"; }
(完全なコマンドラインインターフェイスの機能および/またはbasename
実装のためのより良い名前の選択は、読者の練習問題として残ります。)
答え2
パスを変数に入れ、その長さの数を使用して、次のようにフルパス名から必要な部分文字列のみを取得できます。
$ pth="/source/path/";
$ for i in $path*.pdf; do \
ln -s "$i" ./"${i:${#pth}}"; \
done