ファイルを自動的にタッチするシェルスクリプト

ファイルを自動的にタッチするシェルスクリプト

ディレクトリ内のすべてのファイルにアクセスするシェルスクリプトを作成しました/tmp。ところで 'というエラーメッセージが表示されます /bin/touch: Argument list too long。問題の原因は何ですか?

#!/bin/bash

dayNo=1
while test $dayNo -le 200
do
    touch `find /tmp/`
    sleep 86000
done

答え1

/tmpファイルが多すぎます。不適切コマンドラインにすべての名前を一度に表示します(パスにスペースがある場合は、使用しているバージョンも安全ではありません)。

良いニュースは、find次のように安全かつ正確に実行できることです。

find /tmp -exec touch -c '{}' +

すべてのファイルは以前と同じように検索し、必要なだけ実行してtouch毎回必要な数のファイルを実行します。

find-execオプション一致するファイルを実行し、パスを置き換えるコマンドを受け入れます{}+つまり、複数のファイルに対して一度に、または各ファイルに対して一度だけコマンドを実行します\;touch


コメントで指摘したように、-execdir touch -c '{}' \;これは厳しく安全ですが、シングルユーザーシステムでは少し遅く、大きな利点はありません。まず、各サブディレクトリに切り替えてから、毎回そのディレクトリのファイルに対してのみコマンドを実行して、特定の競合状態を回避します。この-execdirオプションは非標準拡張ですが、サポートされています。牛に似た一種の栄養FreeBSDオープンBSDネットワークBSDオペレーティングシステム finds;他の商用 Unices には通常この機能はありません。何を使用しているのかわかりませんが、該当する場合は上記を検討してください。

答え2

シェルは、逆引用符内の式の結果をその行に置き換えます。ただし、システムにはコマンドパラメータリストの長さに制限があります。したがって、/ tmpに何千ものファイルがある場合は、何千もの名前を引数としてコマンドを生成しようとします。これは失敗しました。

これをより簡単に実行できる方法はいくつかあります。検索自体からコマンドを実行できます。ほとんどの最新バージョンでは、分割して各制限を持つ複数のtouch個別のコマンドを実行できます。

find /tmp -exec touch {} +

答え3

質問のバックティック呼び出しの主な問題は、最初にfindコマンドが/ tmpの下のすべてのファイルを一覧表示し、次にその(巨大な)リストが引数として渡されることです。touchこれは単一の呼び出しには多すぎます。ファイル名にスペース、改行、セミコロン、アンパサンド、パイプ文字などの文字が含まれている場合でも問題が発生する可能性があります。

次の構造を使用する方が良いです。

find /tmp -type f -exec touch -c '{}' +

このfindコマンドは再帰的に一覧表示されます/tmp

-type f通常のファイルのみを選択するように find に指示する

この-cオプションを使用すると、touchTouchが存在しないファイルを生成するのを防ぎます。

例では、いくつかのロジックを省略しているように見えますが、200回だけ実行したい場合は、次のことを試すことができます。

#!/bin/bash

日数= 1
$dayNo -le 200 テスト時
する
    /tmp -type f -exec touch -c '{}' + 検索
    睡眠 86000
    日数=$(式1 + ${日数})
完璧

関連情報