bashのwhereコマンドレットと同じものは何ですか?

bashのwhereコマンドレットと同じものは何ですか?

コマンドレットは私がPSでよく使うものですが、とても便利です。

名前が「test」で始まるすべてのファイルを取得するには、次のようにします。

ls | ?{$_.name -like 'test*'}

nix管理者がbashでこれを行うためのきちんとした方法は何ですか? Bashは明らかにオブジェクトベースではないテキストなので、コマンドは次のようになります。

ls | ?{<column#> -like 'test*'}

私はlsコマンド(ls test*動作しますがコマンドによって異なります)について尋ねるのではなく、このようなフィルタを介して出力をパイプする方法に対応する簡潔なbashを探しています。

答え1

長い話を短く:それが気に入らなければls、それでもそうです。いいえ以下のコマンドに関連してを使用してくださいarr=(); for foo in * [!*]*; do [[ $foo == test* ]] && arr+=("$foo"); done。これは基本的にarr=list_files.filter((i) -> (i.glob_match('test*'));別の言語で書くことです。

しかし、読み続けると、これはls大丈夫で、これらのテストを直接配列割り当てにスキップする必要があることに気付くでしょうarr=(test*)(mikeservは私が最初にこのことをする必要があることに気づきました)。

テキストフィルタリングのクイックレビュー

他の人がコメントで述べたように、Unixシェルはオブジェクトパッケージではなくテキストストリームをパイプします。 Unixの世界では、Windowsよりファイル名やその他の多くのスペースに多くのコンテンツを許可するため、シェルワードの境界だけが安全です。幸い、許可されていないファイル名と同じ場合は、\0ストリームでも使用できます。

grep友達は引き続きデフォルトのテキストフィルタとして機能します。食べるワイヤー標準入力またはファイル内の与えられた正規表現と一致し、一致する(または反対の)行または-vセクション(-o)を次のように提供します。標準出力、まだ使用するのに安全ではない別のストリームです。

これは、ほとんどのコードや詩など、改行で区切られたテキストでは機能しますが、ファイル名では機能しません。ファイル名には改行を含めることができ、grepファイルには2つの別々の行を表示することができますls

Unixシェルのプログラムでは、ワイルドカードはどのように見えますか?

UNIXシェルでは、ワイルドカード文字はターゲットプログラムではなくシェルによって処理されます。これは混乱を招き、test*そのセクションが関連性があると考えると同時に状況をより一貫していますls

fileがあると仮定すると、test1lstest2test3次のようになります。

ls test1 test2 test3

それは基本的にあなたがそれに何をしているのかわかりません。

内部的にtest*シェルに拡張性格。これで構造体があるので、for varname in [word-list]; do [commands]; done次のようにすることができます。

for i in *; do
    if i matches the pattern; then
         do something
    fi # that marks endif
done

[[Bashにはパターンマッチングを実行できるものがあります。与えられた構造に対して、[[ lhs == rhs ]]bashはそれがlhs上記のパターンと一致することを確認しますrhs。私たちの場合は、[[ $i == test* ]]このセクションを使用できますi matches the pattern最小POSIXシェルでは使用できませんcase。代わりに使用してください。

いくつかのタスクを追加する必要がありますdo something。 Bashに配列があります:

# Arrays doesn't exist in POSIX standard too.
a=() # an empty array, since bash is weak-typed this doesn't mean anything
b=(foo bar baz) # array are assigned with, well, list-of-words.
for i in *; do
    if [ $i == test* ]]; then
         a+=("$i") # quoting avoids some word-splitting and you know what += is
    fi # that marks endif
done
# and here do something to your lonely array, like those described in 
# gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html

ここにもう一つ。 Unixシステムでは、慣例的に.隠されたファイルは、で始まるファイル名で表示され、*含まれません。.*明示的に追加しますが、.現在のディレクトリを表し、..basedir(Windowsと同じ)を表すので、削除しようとしています。.[!.]*ドット、非ドット文字、ゼロ文字を含むすべての数字を意味するため、使用できます。で始まらないtest*ので、あなたのビジネスとは関係ありません。test.

extglob複数のパターン「または」の場合(最初に実行)、アイテムを使用するか、複数のshopt -s extglobパターンを許可する場所に全体をラップできます@(patt1|patt2)case

しかし、なぜそのようなものが必要なのでしょうか?a=(test*)。を使用するtest*と、一致する単語のリストが提供されます。複数モードの場合を使用してくださいa=(test* tset*)

しかし、グローバルマッチが失敗した場合はどうなりますか?

globが一致するものがない場合、単語リストにはglobパターン自体が残ります。これは怠惰なシェルユーザーにとっては大丈夫に見えるかもしれませんが、私たちのような真剣なスクリプターにとってはそうではありません。

shoptnullglob幸い、bashにはglobモードを復元しないプログラムがあります。shopt -s nullglob有効にするには、まず使用してください。これを他のPOSIXシェルから移植できるようにするには、for-and-caseフィルタリングに戻ります。

人々はこの解決策をどのように得ますかls

--ワイルドカードとして指定したい項目が次でない場合は、次の項目を追加test*すると、一部のオプションで次の*test*ファイル名が認識されることがあります。オプション終了マーク-test123ls--慣例によると

# So what you need is globbing:
echo test*
# But those are not clear enough since echo only adds spaces between them. Use newlines:
printf '%s\n' test*
# But our screen doesn't have so many lines. Ah, yes, ls can make it into columns:
ls -- test*
# But it lists the contents of the directory test233/. Let's ask it not to:
ls -d -- test*
# Oh, good enough, let's add some color and some pretty type indicator:
ls -dF --color=auto -- test*

したがって、あなたの簡単な質問は次のとおりですls -d test*。しかしそれはいいえ単一コマンドの場合は、lsきれいな印刷にのみ使用します。

もしそうなら、パイプのファイル名は常に愚かですか?

\0いいえ。一部のプログラムでは、区切り記号(およびfind -print0)を追加/使用して、xargs -0人々が安全に使用できると思うようにします。残念ながらそれは必要ですいくつかのヒントシェルがそれを受け入れるようにしてください\0。だから...

多くのシェルにはまだ優れたワイルドカードソリューションがあります。findディレクトリを再帰的に移動し、条件に基づいて見つかったファイル名を印刷します。これは、多くの場合、ファイルを再帰的にリストするために使用されます。 Bashには次のものがあります。

shopt -s globstar
for i in **; do
    try-some-test || continue
    do-something
done

うまいことです。

しかし、bashすべてを提供するわけではありません。たとえば、きちんとした並列命令はなく、ネイティブコードほど速く実行されません。そのため、人々は他のプログラムを使ってparallel仕事をします。今、私たちはそれを持っているので、\0それほど悪くなく、find -print0食べることができます。

答え2

これにより、「test」で始まるファイルのみが返されます。

ls | grep '^test'

その他の例:

これにより、「test」という単語を含む行のみが返されます。レコードごとに1行を取得するために、 "ls"の代わりにls -al"を使用しました。

ls -al | grep "test"

これにより、testまたはword2を含むすべての行が返されます。

ls -al | grep "test\|word2"

これにより、「test」文字列を含まないすべての行が返されます。

ls -al | grep -v "test"

実際に列単位で実行するには、次のことができます。

ls -al | awk '$9 ~ /^test/'

ここで $9 は、私の Debian コンピュータのファイル名を表す列 9 を表し、下の正規表現は「test」で始まるという意味です。 awkは、フィールド区切り文字として扱われる空白および/またはタブおよび/または改行文字で列を区切ります。

答え3

beginning"test"(またはより複雑な)を含むすべてのファイルをフィルタリングするには、egrepを使用して正規表現パターンマッチングを適用できます。

ls出力でこの文字で始まるファイルを検索してください。D

$ ls |egrep "^D"
Desktop
Documents
Downloads
Dropbox

正規表現を使用しないと、次の結果が表示されます。

$ ls |grep D
Desktop
Documents
Downloads
Dropbox
README
Vuze Downloads

関連情報