ファイル名にスペース、*、?、$、%などが含まれているディレクトリ内のファイルのリストを提供するように要求するスクリプトを書いています。これを行うにはどうすればよいですか。複数の投稿を確認しましたが、自分に適したものが見つかりませんでした。 grepを使用してこれを達成することは可能ですか?
grep -E
は、必要なことを行う必要があります。一部の文字はバックスラッシュでエスケープする必要があるので、さらに追加して結果が期待したものと異なる場合は、エスケープしてもう一度やり直してください。 |
はor
...です.
$ ls | grep -E '\s|\*|\?|\$|%'
all this.txt
all?this.txt
all*this.txt
all%this.txt
all th*s.txt
all$.txt
printf '<%s>\n' *[[:space:]*?$%]*
隠しファイルは報告されません。 [[:space:]]
がマルチバイトのスペース文字(UTF-8の" "
( EM QUAD )など)に一致するかどうかは、シェルに依存します(dash
のようなものはマルチバイト文字はまだ認識されていません)
例:
$ touch sane 'a%b' $'with\nnewline' $'with space' $'with em-quad'
$ printf '<%s>\n' *[[:space:]*?$%]*
<a%b>
<with em-quad>
<with
newline>
<with space>
ファイルの安全なリストは、引用符なしの*
を使用して作成され、検索は使用されません。
$ echo *
テストするファイルをいくつか見てみましょう。
$ mkdir test-dir; cd test-dir
$ touch clean normal_file 'a%b' 'has two spaces' '*' 'a*b' '?' 'a?b'
$ touch '$' 'a$b' '%' 'a%b' $'new\nline' $'em\u2001quad' 'normal_file'
上記のファイルを使用して、echo *
コマンドが生成されます。
? $ * % a?b a$b a*b a%b clean em quad has two spaces new
line normal_file
名前に改行が含まれるファイルがあるため、スペースで区切られたリストには2行あります。
ファイルを確認する簡単な方法は、printf '%q'
でファイル名を引用し、printf '%q\n'
のように新しい行を追加することです。これにより、ファイルのクリーンなリストを取得できます。
$ printf '%q\n' *
\?
\$
\*
%
a\?b
a\$b
a\*b
a%b
clean
$'em\342\200\201quad'
has\ two\ spaces
$'new\nline'
normal_file
もちろん、プレーンな*のように、すべてではなくいくつかのファイルを選択する必要があります。
そこで、一致するすべての文字のパターンを作成します:?$*%
。
ただし、これらの文字のほとんどは「特殊」であり、一部の注文で表示される場合は引用する必要があります。具体的には、*
または?
が$
の後に続く場合、シェルによって展開され、問題が発生する可能性があります。$
を引用する必要があります。
次に、他のすべての文字を引用符で囲む簡単な方法は、printf '%q' ?\$*%
を使用することです。これにより、\?\$\*%
が生成されます。バックスラッシュが厳密に必要ではない場合、悪影響はありませんが、エスケープされた文字は引き続き機能します。
そのリストにいくつかの空白文字を追加する必要があります。しかし、改行の挿入は深刻な問題になります。文字クラス内の改行を処理する最も簡単な方法は、[[:space:]]
を使用することです。これには、改行、スペース、タブ、およびその他のスペース文字がem-dashとして含まれます。
したがって、コマンドは次のようになります。
$ printf '%q\n' *[\?\$\*%[:space:]]*
\?
\$
\*
%
a\?b
a\$b
a\*b
a%b
$'em\342\200\201quad'
has\ two\ spaces
$'new\nline'
clean
およびnormal_file
ファイル名は、必要に応じてリストされていないことに注意してください。
これは本当にシンプルで、1979年のBourne Shellですでに機能しています。
for i in *
do
case "$i" in
*\ *) echo blank $i;;
*\?*) echo qmark $i;;
esac
done
一行で:
for i in *; do
case $i in
*\ *|*\?*|*\**|*\$*|*%* ) echo "Special character $i"; ;;
* ) echo "normal file $i"; ;;
esac
done
必要に応じてケースを追加してください...