パスを持つファイルが与えられた場合
/foo/bar/a.b.c.d.x
最後の拡張子が/foo/bar/abcd*に一致するすべてのファイルを見つけることができるようにしたいです。
これが私が今まで使ってきたものです。
findSiblingFiles () {
local filePath="$1"
find "$(dirname "$filePath")" -name "$(basename "${filePath%.*}").*"
}
これはほとんどの場合機能しますが、ファイルに角かっこ(例: "abc [helloworld].x")が含まれている場合は機能しません。バックスラッシュが角かっこを超えて動作するようにすることはできますが、そうするには関数で正規表現を使用してバックスラッシュを追加する必要があります。では、混乱した領域が生じて何か抜けたものがあるのだろうか。より簡単な方法これを行うには。
理想的には、次の内容を含むファイルを見つける必要があります。どのファイル名の文字(角かっこ、中かっこ、かっこなど)と時間効率が考慮されます。
ベストアンサー1
このパターンに一致するすべてのファイルを表示するには、/foo/bar/a.b.c.d.*
次のようにします。
printf '%s\n' /foo/bar/a.b.c.d.*
パターンに一致するすべてのファイルを表示するには/foo/bar/a.b.c.[helloworld].*
(ここでは[hellowerld]
テキスト)、次を使用します。
printf '%s\n' /foo/bar/a.b.c.'[helloworld]'.*
つまり、文字通り表現しなければならないパターン部分を参照します。
その文字列を取得し、最後の文字列を削除し、次に置き換えたときに得られたパターンと一致するその文字列の下のすべてのファイルを表示a.b.c.[helloworld].x
するには/foo/bar
.x
.*
string='a.b.c.[helloworld].x'
printf '%s\n' /foo/bar/"${string%.*}".*
ここで考慮すべき唯一のことは、参照変数置換の拡張です。
bash
シェルでこれを再帰的に実行し、隠された名前を含めてから、次を使用しますか?
shopt -s globstar dotglob
string='a.b.c.[helloworld].x'
printf '%s\n' /foo/bar/**/"${string%.*}".*
あなたの機能は次のように書くことができます(サブディレクトリから検索する必要はありません)。
findSiblingFiles () {
printf '%s\n' "${1%.*}".*
}
または、パターンが一致しない場合は何も出力せず、空白行も出力しない場合は、
findSiblingFiles () (
shopt -s nullglob
set -- "${1%.*}".*
[ "$#" -gt 0 ] && printf '%s\n' "$@"
)
最初の引数の「尾」のみを変更するため、指定されたファイル名に実際にドットがあることを確認したくない限り、ディレクトリパスからファイル名を区切る必要はありません。以下のコードではこれを行います。 。
findSiblingFiles () (
shopt -s nullglob
if [[ ${1##*/} != *.* ]]; then
echo 'Filename has no suffix' >&2
return 1
fi
set -- "${1%.*}".*
[ "$#" -gt 0 ] && printf '%s\n' "$@"
)
テスト:
$ findSiblingFiles ~myself/local/src/project/doc/document.txt
/home/myself/local/src/project/doc/document.man
/home/myself/local/src/project/doc/document.mdoc
/home/myself/local/src/project/doc/document.txt