フォルダー内の最後の2つのファイルを除くすべてを削除するスクリプトを作成しました。
#!/bin/bash
ls -1 --quoting-style=Shell-always /path/to/some/folder \
| head -n -2 \
| xargs printf -- "'/path/to/some/folder/%s'\n" \
| xargs Sudo rm -rf
このスクリプトは、毎日cronジョブとして実行されます。
その理由は次のとおりです。
ls -1
を使用してすべてのファイルのリストを取得します(したがって、1行に1つのファイルを取得します)。
head -n -2
;を使用してリストから最後の2つを削除します。
ls
は相対パスを出力するため、xargs printf
を使用してフォルダーパスを追加し、絶対パスにします。
xargs
を使用してSudo rm -rf
に送信します。
誰でもこのフォルダにアクセスできるため、誰でもこのフォルダ内のファイルを作成および削除できます。
問題は:Sudo rm -rf
は怖いです。 xargs Sudo rm -rf
は非常に怖いです。
削除する巧妙なファイルを作成することで(誤ってまたは故意に)他のフォルダー/システムを損傷することがないようにしたいと思います。私は知りません、次のような巧妙なもの:
file with / spaces.txt
その結果、非常に怖いSudo rm -rf /
になる可能性があります。
EDIT:私の間違いです。ファイル名に/
を含めることはできないため、この特定の問題は発生しませんが、他のリスクがあるかどうかについての質問はまだ残っています。
これが--quoting-style=Shell-always
を使用している理由です。これにより、スペースのあるファイルでのトリックを防ぐことができます。しかし、今私は誰かがファイル名にスペースと引用符で余分な巧妙なことができるかどうか疑問に思っています。
スクリプトは安全ですか?
注:Sudo
が必要なのは、mount
を使用してマップされたネットワークドライブからリモートでフォルダーにアクセスしており、Sudoなしでは機能しないためです。
Linuxでは、任意の文字は次を除く文字を構成する有効なファイル名です。
\0
(ASCII NUL):Cの文字列終了に使用される/
(スラッシュ):パス分離に使用だから、あなたのアプローチは、あなたが想像できるように、多くの場合、間違いなく機能しません。ファイル名の改行(\n
)を処理しますか? (ヒント:No)。
いくつかのメモ:
ls
;専用ツールを使用します(ほとんどのユースケースには少なくとも1つあります)xargs
を呼び出すたびに、find ... -exec
で逃げられるかどうかを確認してください。ほとんどの場合、find
だけで十分です。これらは今のところあなたを連れて行くと思います。 steeldriver はすでにコメントでNULで区切られたアイデアを提供しています(printf -- '%s\0' /path/to/some/folder/* | head -zn -2 | xargs -0 rm
)。これを出発点として使用します。
xargs
はいくつかの引用符をサポートします。任意の引数を受け入れることができる単一引用符、二重引用符、またはバックスラッシュを使用しますが、Bourneのようなシェルの引用構文とは異なる構文を使用します。
Ubuntuで見つかったls
のGNU実装には、xargs
入力形式と互換性のある引用モードがありません。
ls --quoting-style=Shell-always
はksh93、bashおよびzshシェルの構文と互換性がありますが、ls
の出力がls
と同じロケールでシェルによって解釈された場合にのみ、それが出力されます。また、BIG5、BIG5-HKSCS、GBK、GB18030を使用しているロケールなどの一部のロケールは避ける必要があります。
したがって、これらのシェルを使用すると、実際に次のことができます。
typeset -a files
eval "files=($(ls --quoting-style=Shell-always))"
xargs -r0a <(printf '%s\0' "${files[@]:0:3}") ...
しかし、それは次のような利点はほとんどありません
files=(*(N)) # zsh
files=(~(N)*) # ksh93
shopt -s nullglob; files=(*) # bash
唯一役立つのは、ls
の-t
オプションを使用して、mtime/atime/ctimeまたは-S
/-V
でファイルをソートする場合です。ただし、その場合でも、zsh
を使用することもできます。
files=(*(Nom))
たとえば、mtimeでファイルをソートするには(-S
にはoL
を、-V
にはn
を使用します)。
最近変更された2つの通常ファイルを除くすべてを削除するには:
rm -f -- *(D.om[3,-1])
¹まだ長さの制限がいくつかあります(execve()
およびいくつかの非GNU xargs
実装でははるかに低い任意のもの)、およびいくつかの非GNU xargs
実装はシーケンスを含む入力をチョークします有効な文字を形成しないバイト数。