コマンドラインの*から除外


14

aの使用*が事実上避けられない状況がたくさんありrm -rf *ます-例えば、何千ものサブフォルダーとファイルを保持するフォルダー内。

しかし、rmコマンドから1つまたは2つのファイルまたはフォルダーのみを除外する場合はどうでしょうか。私は自分のやり方をグーグルで調べましたが、ここで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' *ですか?

たぶんから物事を除外するためにも、一般的な可能性*(のようなので、他のコマンドはcpmv...自分自身を実装する必要はありませんか)?のようなもの*{'one','two','three'}ですか?


3
1つまたは2つのファイルのみを保持する場合、最も簡単で簡単な方法は、それらのファイルを別の場所に移動し、残りのすべてのファイルを消去して、保持したファイルを移動することです。もっと多くのファイルを保持したい場合findは、この--deleteオプションで使用します(rm各ファイルに対して実行する必要はありません。これは不必要なオーバーヘッドです)。
ヘネス

それは可能性がありますが、それは私が言及したものとほぼ同じくらい精巧です。コマンドをのようなものに組み合わせることができることは知っていますがmv -t /tmp one two three && rm -rf * && mv -t . /tmp/one /tmp/two /tmp/three、明示的に何かを除外する可能性を与えるソリューションを好むでしょう*。確かに、ファイルを別の宛先に移動またはコピーすることがオプションではない状況があります。
デビッド

2
それが、答えとして投稿しなかった理由です。単純に単純な方法(3つの非常に単純なコマンドと1つやや複雑なコマンド)。rmと組み合わせた複雑さは嫌いです。
ヘネス

回答:


33

Bashには、標準のシェル構文との互換性を保つためにデフォルトextglob非アクティブ化されるシェルオプションがあります。Extglob!()?()@()などの追加演算子によって構文を補完します。

スイッチを入れるextglobには、と入力しshopt -s extglobます。それを維持するには、現在のユーザタイプスイッチオンecho 'shopt -s extglob' >> ~/.bashrc

rmの例:extglobを使用すると

rm -rf !(one|two|three)

良い解決策のように思えますが、説明したような状況に陥るたびにオンとオフを切り替えたくもありません。
デビッド

3
@David:shopt物を自分のものに入れることができますが~/.bashrc、傷つけることはありません。
エンゾチブ

私がそれを正しく理解すれば、extglobオプションはまったく効果を変えません*が、代わりに追加の!機能を持つ同様のインジケーター(のような)を追加しますか?その場合、それは素敵なソリューションになります。
デビッド

1
@David:そのとおりです。
チョロバ

1
@David 標準のシェル構文との互換性を維持します。他の状況では、動作が変わる可能性があります。
gerrit

4

私はそれを除いて構築しました(まだドキュメントを追加できなかったので)。

次のようなフォルダがあります:

$ 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

3
これはいいですが、extglobについて知っている場合は本当に必要ありません-askubuntu.com/a/329233/138369-
デビッド

1

extglobの代替として(これは非常に良い回答であり、誰もがshopt -s extglob globstar.bashrcに含める必要があります)、$ 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' ./*
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.