2016-04-04 9 views
1

特定のグロブパターン(例:* .txt)に一致する一連のファイルがあります。私は辞書順で最も高いものを除くすべてを削除したい。Zsh:最高位の辞書順ソート順以外のすべてのファイルを削除する

私は、さまざまな解決策を見つけることを試みたが、私はで出てきたとしても最高のもの、醜いです:

set -A files *(N) 
set -A to_remove ${(O)files} 
shift to_remove 
foreach f in $to_remove 
do 
    echo rm $f 
done 

to_removeが空の場合、このエラーを与えるだろうので、私は、rm $to_removeを書いていません)。

もっと簡単な方法がわかっている場合は、いくつか提案してください。

+0

「最も高い」とは、最小または最大を意味しますか?例えば。 'a.txt b.txt c.txt'があれば、' a.txt'や 'c.txt'を保存しますか? – Gilles

+0

私はc.txtを保存したいと思います。 – user1934428

答えて

1

subscript rangeを使用します。負の数は最後から数えます。

if ((#files > 1)); then rm -- ${files[1,-2]}; fi 

アレイがソートされていない場合は、sort it firstです。

if ((#files > 1)); then rm -- ${${(o)files}[1,-2]}; fi 

あなたはこのためのファイルを生成している場合は、glob qualifierから選択を行うことができます。

files=(*.txt(N[1,-2])) 
if ((#files)); then rm -- $files; fi 
+0

あなたの解を 'echo * .txt(N [1、-2])| xargs rm --'に適合させました。どうもありがとう! – user1934428

+1

@ user1934428これはしないでください:空白や '\ '" 'を含むファイル名が壊れます。コマンドラインの長さ制限を実行すると、[zshの組み込み関数を使う](http://unix.stackexchange.com/質問/ 156100/what-does-this-zsh-to-the-argument-list-is-too-long-do)を使用してください。 – Gilles

1

最初に配列を作成する必要はありません。ファイル名展開によって返されるファイルをフィルタリングする範囲を指定することができます。

$ touch a b c 
$ print -l *(N) 
a 
b 
c 
$ print -l *(N[1,-2]) 
b 
c 

したがって、rm *(N[1,-2])を使用すると、最初に一致するファイル以外のすべてを削除できます。

あなたは、アレイと同じことを行うことができます:あなたがソートされた配列内のファイル名を持っている場合は、

$ foo=(a b c) 
$ print -l $foo[2,-1] 
b 
c 
+0

@ Gillesが答えて書いたように、範囲は '[1、-2]'でなければなりません。 – user1934428

+0

ああ、そうです。私はあなたのオリジナルのように 'O'でソートし始め、それを落として範囲を調整するのを忘れました。 – chepner

関連する問題