*
の使用が事実上避けられない状況がたくさんあります。 rm -rf *
は、数千のサブフォルダーとファイルを保持するフォルダー内にあります。
しかし、rm
コマンドから1つまたは2つのファイルまたはフォルダーのみを除外する場合はどうでしょうか。私は自分のやり方をグーグルで調べましたが、 here のようにfind . -depth -not \( -name 'one' -o -name 'two' \ -o -name 'three' \) -exec rm {} \;
のような非常に複雑なソリューションしか見つかりませんでした。
これをより簡単な方法で行う可能性はありますか?find
への迂回なしで。例えば。 rm -rf --exclude='one' --exclude='two' --exclude='three' *
rsyncのように、またはrm -rf -e 'one','two','three' *
のように?
*
から物事を除外する一般的な可能性もあります(したがって、cp
、mv
などの他のコマンドは、独自に実装する必要はありません)。 *{'one','two','three'}
のようなものですか?
Bashにはextglob
というシェルオプションがあります。これは、標準のシェル構文との互換性を保つために デフォルトで非アクティブ化 です。 Extglob は、!()
、?()
、@()
などの追加演算子によって構文を補完します。
extglob
をオンにするには、shopt -s extglob
と入力します。現在のユーザーに対して有効にするには、echo 'shopt -s extglob' >> ~/.bashrc
と入力します。
Rmの例:extglob
では、次を使用できます。
rm -rf !(one|two|three)
そのために except を作成しました(まだドキュメントを追加できなかったので)。
次のようなフォルダがあります:
$ ls
a b c d
except b d
と入力すると、a
とc
が表示されます
$ except b d
ac
これで、rm
にパイプできます。
except b d | xargs -0 rm
これは覚えにくいかもしれませんので、なぜrm-except
と呼ばれる例外の上にスクリプトを作成しないのですか:
#!/usr/bin/env bash
except "$@" | xargs -0 rm
ls-except
も同様に簡単です:
#!/usr/bin/env bash
except "$@" | xargs -0 ls
Extglobの代替として(非常に良い答えであり、誰もが.bashrcにshopt -s extglob globstar
を含める必要があります)、 $ GLOBIGNOREグローバル変数 を使用できます。 「foo.txt」と「bar baz.txt」を除くすべてのファイルを取得するとします。
GLOBIGNORE=foo.txt:'bar baz.txt'
...ただし、これにより、シェルオプションdotglob
がオンになります。つまり、*
は、ドットで始まるファイル(通常は非表示)に一致します。したがって、実際には2つのコマンドが必要です。
GLOBIGNORE=foo.txt:'bar baz.txt'
shopt -u dotglob
これはグローバル変数であるため、ログアウトまたは次のいずれかの方法で$ GLOBSTARが設定解除されるまで、使用するすべてのグロブに影響します
GLOBIGNORE=
また、変数に渡されたリテラル文字列でのみ機能します。 $ GLOBIGNOREを設定し、これらのコマンドの違いを見ると、私が何を意味するかがわかります。
printf '%s\n' *
printf '%s\n' ./*