web-dev-qa-db-ja.com

検索を使用せずにスペースと特殊文字を含むファイル名を一覧表示する方法

ファイル名にスペース、*、?、$、%などが含まれているディレクトリ内のファイルのリストを提供するように要求するスクリプトを書いています。これを行うにはどうすればよいですか。複数の投稿を確認しましたが、自分に適したものが見つかりませんでした。 grepを使用してこれを達成することは可能ですか?

2
KLMM

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
1
stevieb
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>
3

ファイルの安全なリストは、引用符なしの*を使用して作成され、検索は使用されません。

$ 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ファイル名は、必要に応じてリストされていないことに注意してください。

2
user79743

これは本当にシンプルで、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

必要に応じてケースを追加してください...

0
schily