OverTheWireバンディットチャレンジのレベル5 を行うための効率的な方法を見つけようとしています。
とにかく、私にはたくさんのファイルがあり、次の基準を尊重するファイルは1つだけです。
現在、find
コマンドを使用しており、最後の2つの条件に一致するファイルを見つけることができます。
find . -size 1033c ! -executable
ただし、人間が読み取れないファイルを除外する方法はわかりません。その課題で見つけたソリューションは-readable
テストパラメータですが、これは機能しないと思います。 -readable
はファイルのアクセス許可のみを確認し、その内容は確認しませんが、チャレンジの説明ではASCIIファイルなどを要求します。
はい、find
を使用して適切なサイズの実行不可能なファイルを検索し、次にfile
を使用してASCIIを確認できます。何かのようなもの:
find . -type f -size 1033c ! -executable -exec file {} + | grep ASCII
ただし、問題は思ったほど単純ではありません。 「人間が読める」はひどくあいまいな用語です。おそらく、あなたはテキストを意味します。わかりましたが、どのようなテキストですか?ラテン文字ASCIIのみ?完全なUnicode?たとえば、次の3つのファイルについて考えてみます。
$ cat file1
abcde
$ cat file2
αβγδε
$ cat file3
abcde
αβγδε
$ cat file4
#!/bin/sh
echo foo
これらはすべてテキストで人間が読める形式です。次に、file
がそれらをどのように構成するかを見てみましょう。
$ file *
file1: ASCII text
file2: UTF-8 Unicode text
file3: UTF-8 Unicode text
file4: POSIX Shell script, ASCII text executable
したがって、上記のfind
コマンドはfile1
のみを検索します(この例のために、これらのファイルに1033文字あると想定しましょう)。 find
を展開して、文字列text
を探すことができます。
find . -type f -size 1033c ! -executable -exec file {} + | grep -w text
-w
を使用すると、grep
はtext
がスタンドアロンWordとして検出された行のみを印刷します。そのすべきはあなたが望むものにかなり近いですが、説明に文字列text
が含まれている可能性のある他のファイルタイプがないことは保証できません。
-exec
は主に、見つかったファイルを処理するために使用され、テストとしても機能します。したがって、他の基準に追加することができます。
find . \
-size 1033c \
-not -executable \
-exec sh -c 'file {} | grep "text$"' \;
パターンが見つからなかった場合、grep
はゼロ以外を返し、sh -c "COMMAND"
は、評価の結果を返します(有効な場合)。したがって、これはfile <filename>
はtext
で終わるものを吐き出します。たとえば、 「UTF-8 Unicodeテキスト」または「ASCIIテキスト」。ただし、「非ISO拡張ASCIIテキスト、エスケープシーケンス付き」は不可。
単一行では、xargs
を通過するよりも短くなります。
find . -size 1033c -not -executable -exec sh -c 'file {} | grep "text$"' \;
sh -c 'file {} | grep "text$"'
任意のカスタムコマンド。非常に複雑なものをチェックしたい場合は、シェルスクリプトを用意し、代わりにそれを使用することをお勧めします。
find . -size 1033c -not -executable -exec is_human_readable.sh {} \;
長期的に見ると、シェルの履歴よりも保守が簡単です。
#!/bin/sh
file "$@" | grep "text$" > /dev/null
find . -size 1033c ! -executable -exec file {} +
あなただけを使用する必要があります:
find inhere -size 1033c
それはあなたにパスワードを含む唯一のファイルを与えます。
ディレクトリの内容に対して以下を実行するだけです:
$ file -- *
-file00: data
-file01: data
-file02: data
-file03: data
-file04: data
-file05: data
-file06: data
-file07: ASCII text
-file08: data
-file09: data
$ cat -- \-file07
<output>
bandit4@bandit:~$ ls
inhere
bandit4@bandit:~$ file inhere/*
inhere/-file00: data
inhere/-file01: data
inhere/-file02: data
inhere/-file03: data
inhere/-file04: data
inhere/-file05: data
inhere/-file06: data
inhere/-file07: ASCII text
inhere/-file08: data
inhere/-file09: data
bandit4@bandit:~$ pwd
/home/bandit4
bandit4@bandit:~$ cat /home/bandit4/inhere/-file07
koReBOKuIDDepwhWk7jZC0RTdopnAYKh
bandit4@bandit:~$
あなたはこれを試すことができます
find . -size 1033c ! -executable -exec file {} +
チャレンジではgrep
は許可されていません。パスワードファイルは「ASCIIテキスト、非常に長い行」として報告されます
find . -size 1033c ! -executable|xargs file|grep "ASCII text" |awk -F: '{print $1}'
この組み合わせコマンドをお試しください。それは私のステーションで動作します。
find . -type f -size 1033c ! -executable | xargs file | grep text
ワンライナーのファン
上記のほとんどで、findとgrepを使用してこのバンディットレベルのパスワードを検索するより長い方法が、最もわかりやすいコマンドだと思います。
find . -type f -size 1033c ! -executable -exec file {} + | grep ASCII
しかし、「file」コマンドをさらに使用した後、ディレクトリ全体のファイルタイプをチェックすることにより、この方法で人間が読めるファイル(このレベルでは別名ASCII))を見つけるのが非常に簡単であることに気付きました。inhereディレクトリ「-filexx」という名前のファイルを保持するか、file ./*
を使用してinhereディレクトリ全体をすばやく確認します
これが私のアプローチでした。
bandit4@bandit:~/inhere$ file ./*
./-file00: data
./-file01: data
./-file02: data
./-file03: data
./-file04: data
./-file05: data
./-file06: data
./-file07: ASCII text
./-file08: data
./-file09: data
bandit4@bandit:~/inhere$ cat ./-file07
koReBOKuIDDepwhWk7jZC0RTdopnAYKh
find -type f ! -executable -size 1033c
演習からファイルを取得します
人間が読めるファイル名を除外するには、[:print:]
(printable)character class nameを利用できます。そのようなクラスの詳細については、grep
のマニュアルを参照してください。
find . -type f -size 1033c -name "[[:print:]]*" ! -executable
考え直してみると、「人間が読める」要件は、ファイルの名前ではなく、コンテンツを参照している可能性があります。つまり、textファイルを検索することになります。それはもう少しトリッキーです。 @D_Byeがコメントで提案したように、file
コマンドを使用してファイルのコンテンツタイプを判別する必要があります。ただし、パイプの後にfile
を実行することはお勧めしません。ファイル名を表示するタスクが複雑になるためです。これが私が提案するものです:
find . -type f -size 1033c ! -executable -exec sh -c 'file -b $0 | grep -q text' {} \; -print
これは、file
- partがどのように機能するかを簡単に示したものです。
-exec
述語は、以前のすべての条件を満たす(タイプ、サイズ、実行不可)FILENAME
ごとにsh -c 'file -b $0 | grep -q text' FILENAME
を実行します。sh
)がこの短いscript:file -b $0 | grep -q text
を実行し、$0
をファイル名に置き換えます。file
プログラムは、各ファイルのコンテンツタイプを決定し、この情報を出力します。 -b
オプションは、テストされた各ファイルの名前を出力しません。grep
file
プログラムからの出力をフィルタリングし、 "text"を含む行を検索します。 (file
コマンドの典型的な出力がどのように見えるか、実際に見てください。)grep
は-q
(quiet)オプションが指定されているため、フィルタリングされたテキストを出力しません。これは、exit statusを0
( "true"を表す-フィルターされたテキストが見つかった)または1( "error"を意味する)に変更するだけです。テキスト "text"はfile
からの出力に表示されませんでした。grep
からの真/偽の終了ステータスは、sh
によってfind
にさらに渡され、「-exec sh -c 'file $0 | grep -q text' {} \;
」テスト全体の最終結果として機能します。-print
コマンドが実行されます(つまり、テストされたファイルの名前が出力されます)。