私はかなり複雑な条件付き削除操作を実行できるUnixコマンドシーケンスを探しています。
ファイルに「[NAME].rec」または「[NAME].mpg」という名前の対応するファイルがない場合、拡張子が「[NAME].cut」および「[NAME].cut.bak」のファイルはすべて削除されます。同じフォルダ。
このコマンドは、最小限のカーネルを持つ統合デバイスで実行する必要があるため、「特殊ツール」は使用されません。たとえば、「ls」と「rm」を使用できますが、「find」は存在しません(つまり、依存したくない外部ツールを介してのみ可能です)。
可能であれば、このコマンドはサブディレクトリからも繰り返し削除する必要があります。
背景は次のとおりです。私は録画されたショーを切り取ることができるLinuxベースのPVR用のツールを開発しています。各録画(拡張子.recまたは.mpg)に対して、クリップマーカーが.cutファイルに保存されます。一部の録音が移動/名前変更/削除されると、その切り捨てられたファイルはディスクから無駄になります。役に立たないカットファイルを削除するためにCで実装しました。さて、(簡単な)システムベースのソリューションがあるかどうか疑問に思います。この場合、「システム」を介してバックグラウンドで実行できるため、アプリの反応性が向上します。
以下は、PVRファームウェアに含まれるコマンドです。
嗜好、fgrep、flash_erase、flash_eraseall、flash_info、無料、getty、grep、ヘッダー、hexdump、ホスト名、id、ifconfig、インストール、kill、killall、ln、ロガー、ログイン、ls、md5sum、mkcramfs、mkdir、mknod、mktもっと見る、インストール並べ替え
私に与えるアドバイスがありますか?
答え1
もっと簡単にすることはできませんが、うまくいきます。名前に改行文字を含むファイルがターゲットディレクトリに存在しないとします。;まず、次のコマンドを使用してコマンドをテストします。
find . -type f \( -name "*.cut" -o -name "*.cut.bak" \) -exec bash -c '[ -f "$(<<< "{}" sed "s/\(.*\/[^.]*\).*/\1/").rec" -o -f "$(<<< "{}" sed "s/\(.*\/[^.]*\).*/\1/").mpg" ] && echo "{}"' \;
リストされているファイルが削除される予定のファイルの場合は、次のコマンドを実行して続行できます。
find . -type f \( -name "*.cut" -o -name "*.cut.bak" \) -exec bash -c '[ -f "$(<<< "{}" sed "s/\(.*\/[^.]*\).*/\1/").rec" -o -f "$(<<< "{}" sed "s/\(.*\/[^.]*\).*/\1/").mpg" ] && rm "{}"' \;
一時的に作成されたディレクトリ階層をテストします。
~/tmp$ tree
.
└── dir1
├── file1.cut
├── file1.cut.bak
├── file1.rec
├── file2.cut
├── file2.cut.bak
├── file2.mpg
├── file3.cut
├── file3.cut.bak
└── subdir1
├── file1.cut
├── file1.cut.bak
├── file1.rec
├── file2.cut
├── file2.cut.bak
├── file2.mpg
├── file3.cut
└── file3.cut.bak
2 directories, 16 files
~/tmp$ find . -type f \( -name "*.cut" -o -name "*.cut.bak" \) -exec bash -c 'if [ -f "$(<<< "{}" sed "s/\(.*\/[^.]*\).*/\1/").rec" -o -f "$(<<< "{}" sed "s/\(.*\/[^.]*\).*/\1/").mpg" ]; then rm "{}"; fi' \;
~/tmp$ tree
.
└── dir1
├── file1.rec
├── file2.mpg
├── file3.cut
├── file3.cut.bak
└── subdir1
├── file1.rec
├── file2.mpg
├── file3.cut
└── file3.cut.bak
2 directories, 8 files
ご覧のように、拡張子を持つすべてのファイル.cut
または.bak
名前と拡張子が同じファイルまたは.rec
既存の.mpg
ファイルが繰り返し削除されます(file1.cut
したがってfile1.cut.bak
削除され、file1.rec
削除file2.cut
され、同じディレクトリにファイルが存在しないため削除されない)。file2.cut.bak
file2.mpg
file3.cut
file3.cut.bak
file3.rec
file3.mpg
答え2
コマンドとシェルが非常に制限されているいくつかの小さな組み込みデバイスでコマンドを実行する必要がある場合(例:欠落find
、最小シェルà la sash
)、可能なアプローチの1つは、これを行うための小さなC(またはC ++)プログラムを書くことです。プログラムを実行可能ファイルにコンパイルします(プログラムをフリーソフトウェアにすることをお勧めします)。
あなたは使うでしょうオンラインテレビファイルツリーを再帰的に移動し、削除するパスの配列(またはベクトルまたはリスト)を作成します。その後、2番目のステップでは、ファイルは効果的に削除されます。関連機能はインターネットテレビ(3)(ファイルツリーナビゲーション)、snprintf(3)(構成ファイル名),訪問(2)(ファイルが存在するかテスト)、統計(3)(ファイルの種類、サイズ、その他のメタデータのインポート)削除(3)(ファイル削除)、基本名(3)、等。
GNUがある場合は、find
それを使用してシェルスクリプトを作成できます(ただし、詳細は実際のシェルによって異なり、特にPOSIXと互換性がないほど小さい場合)。削除するファイル名を一時ファイルにまとめます。その後、後で削除してください。
シェルソリューションに固執し、GNU findを使用できると仮定すると、いくつかのシェルスクリプトがあるかもしれません。
まず、名前付きシェルスクリプト(外部から呼び出す)は一時ファイルを生成し、各&ファイルごとclean-the-mess.sh
に異なる内部シェルスクリプトを呼び出します。consider-cleaning.sh
.cut
.cut.bak
#!/bin/sh
## untested clean-the-mess.sh script
## a temporary file listing files to remove
cleanlistfile=$(tempfile -s .cleanlist)
## on exit, or SIGQUIT, SIGTERM, or SIGINT signal, remove it
trap "rm $cleanlistfile" EXIT QUIT TERM INT
## find every file name .cut | .cut.bak; run consider-cleaning.sh on it
find -type f \( -name '*.cut' -o 'name '*.cut.bak' \) \
-exec consider-cleaning.sh '{}' $cleanlistfile \;
## remove the collected file list
for f in $(cat $cleanlistfile) ; do rm $f ; done
一部のファイル名にスペースが含まれている場合、この方法は機能しません。たぶんあなたは考慮することができますxargs(1)
consider-cleaning.sh
次に、クリーンアップするファイルのリストにファイルパスを追加する内部スクリプトを作成する必要があります。そうかもしれない
#!/bin/sh
# internal untested consider-cleaning.sh script
file=$1
collectlist=$2
case $file in
*.cut)
bas=$(basename $file .cut)
if [ ! -f "$bas.rec" -a ! -f "$bas.mpg" ]; then
echo $file >> $collectlist
fi
;;
*.cur.bak)
bas=$(basename $file .cut.bak)
if [ ! -f "$bas.rec" -a ! -f "$bas.mpg" ]; then
echo $file >> $collectlist
fi
;;
esac
私のスクリプトは証明されておらず、テストされていないため、間違っている可能性があります。#!/bin/sh -vx
これをテストしてデバッグするための最初の行として使用します(一部の実行トレースを取得できます)。
または小さな挿入ルアインタプリタは、いくつかの基本的な生ファイル関連の操作を実行し、Luaでスクリプトを作成します。 Luaは挿入するのが非常に簡単で、小さな通訳者になることができます。