特定の範囲の番号付きファイルを削除するにはどうすればよいですか?


16

folderA始まる番号順のファイルがいくつかありますa_000000。私がしたいのは、特定の番号から始まるファイルを削除することです:a_000750このファイルの最後まで言いましょうfolderA。誰でもシェルスクリプトを使用してこれを行う方法をアドバイスできますか?


これらのファイル名すべてに6桁のサフィックスがあると仮定できますか?
ムル

はい、そうです:) a_000000から数が始まるまで
Tak

5
rm a_000[89]* a_0007[5-9]*
リンツウィンド14

@Rinzwindはこのコマンドを説明してもらえますか?

2
@ user1460166にa_000[89]*は、a_0008またはa_0009で始まるすべてのファイルが含まれ、5から9までの数字でa_0007[5-9]*始まりa_0007、その後に何かが続くすべてのファイルが含まれます。
ムル14

回答:


35

範囲の終わりを知っているか推測できると仮定すると、ブレース展開を使用できます:

rm a_{000750..000850}

上記はa_000750からa_000850までの101個のファイルを削除します(そして、存在しないファイルを参照するファイル名について文句を言います)。そのためのファイルが多すぎる場合は、次を使用しますfind

find . -name 'a_*' | while read file; do 
  [ "${file#./a_}" -gt 000749 ] && rm -v "$file" 
done

ここでは、にfind一致するすべてのファイルが単純にリストされますa_*。リストはwhileループに渡され、各ファイル名が変数に読み込まれます$file。次に、bashの文字列操作機能を使用して、数値部分(findはファイルをとして印刷する./fileため${file#./a_}、数字のみを印刷します)000750以上の場合、ファイルは削除されます。-vあなたはファイルが削除されたかを見ることができますので、ただそこにあります。

上記は正しいファイル名を想定していることに注意してください。名前にスペース、改行、またはその他の奇妙な文字を含めることができる場合は、代わりにこれを使用します。

find . -name 'a_*' -print0 | while IFS= read -rd '' file; do 
  [ "${file#./a_}" -gt 000749 ] && rm -v "$file" 
done

なぜ避けるの[[ですか?
ムル14

1
@muruなぜそれを使用するのですか?たとえば、[[ここで[[ "${file#./a_}" > 000749 ]]は物事を単純化せず、短くすることさえしません。私は不必要な構文を使うのは好きではなく、これはのような単純なシェルでも動作しdashます。
テルドン14

なぜなら[[、スペースと奇妙さをうまく処理できるからです(私は>どちらもあまり気にしません)。
ムル14

1
@muruはい、しかし[私が持っているように変数を引用すれば大丈夫で、はるかに多くのシェルで動作し、より簡単です。
テルドン

あなたが主張する場合。僕の問題じゃない。
ムル14

3

次のようなことができます:

find . -regextype posix-extended -iregex './a_[0-9]{6}' -execdir bash -c '[[ ${1##./a_} > 000750 ]] && echo $1' "removing: " {} \;

または:

find . -regextype posix-extended -iregex './a_[0-9]{6}' | sort | sed '0,/000750/d' | xargs echo

最初の方法は、固定プレフィックスを想定し、それを取り除き、値をチェックします。

2番目の方法は、固定長のサフィックス(および共通の固定プレフィックス)を想定し、その事実に依存しています。そして、辞書式で201は前31に来るが、前にはない031

これをechoコマンドでテストし、正しいファイルがリストされていることを確認したら、rm代わりに使用します。


それらのいずれも動作していません:/
Tak

@ user1460166ああ、それはおそらく正規表現の一致が原因です。更新します。
ムル14

まだ動かない。ところで、ファイルは.pngです:)
Tak

@ user1460166あなたはそれがどのように機能していないかを言うことができますか?
ムル14

私はフォルダにターミナル、CDを開き、あなたの行をコピーして貼り付けますが、ファイルは削除されません
タク

0

POSIXシェルソリューション

terdonの第1の解決策は の特性であるブレース展開、に依存しているbashksh、それは標準で使用することができないが、/bin/shUbuntuの上にシンボリックリンクされたシェル、/bin/dash

/bin/shスクリプトの移植性を信頼する必要がある場合、一般的にこれにアプローチする方法は2つあります。1つはグロビングによるものです。ただcd folderAそこから走りrm a_*ます。もう1つの方法は、while <CONDITION>;do ...doneシェル言語でCループのfor代替ループを実装し、次のように数値をフォーマットすることですprintf

$ sh -c 'i=0;while [ $i -le 750 ]; do filename=$(printf "a_%06d" $i);echo "$filename";i=$((i+1)) ;done'

ここで使用していることに注意してくださいecho。交換するecho "$filename"rm ./"$filename"rm -- "$filename"、あなたはファイルを削除する準備ができたら。また、これはcd、目的のディレクトリに既に移動したときに実行する必要があることに注意してください。

(ab)awkを使用する

Awkは、Cに似た素敵な言語であるため、2つの方法で役立ちます:(1)forループでファイル名を生成し、sprintf関数でフォーマットする、(2)system()コマンドでファイルを削除し、生成されたファイル名とrmコマンドを渡すに/bin/sh

awk 'BEGIN{for(i=0;i<=750;i++){filename=sprintf("a_%06d",i);system("rm "filename);} }'

Perl

ファイル名を「生成」するポータブルなアプローチの考え方を続けると、Perlでも同じことができます。

perl -le 'for(0..750){$fd=sprintf("a_%06d",$_);unlink($fd)}'

0

単純な

rm partialfilename* -f

あなたの例では

rm a_00075* -f

1
申し訳ありませんが、それは範囲ではありません。これらはすべてa_00075...で始まるすべてのファイルです
-Fabby

1
* OPは、物事の範囲を削除する方法についての答えを探している、ワイルドカードです...例えば、ファイル100 1〜を持っていた、と#75に#41を削除したい場合
ジョシュアBesneatte
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.