ファイルでいっぱいのディレクトリがあります。私の目標は、ファイルの先頭にテキストを追加することです。各ファイルの先頭にあるテキストは同じです。これは私の試みです。
#!/bin/bash
for file in `find . -type f -executable`;do
sed '/\#!/bin/bash\/a Hello Word'
done
私のスクリプトは競合のみが発生します。
ベストアンサー1
#!/bin/bash for file in `find . -type f -executable`;do sed '/\#!/bin/bash\/a Hello Word' fi done
このスクリプトには多くの問題があります。
まず、fi
そのif
。
スタイル上(fi
行を削除した後)の前の空白行を削除し、done
その前にスペースを追加しますdo
。しかし、これは比較的些細なことです。
ベストプラクティスによれば、推奨される最新形式の代わりにバックティックを使用してコマンドを置き換えます$(...)
。バックティックのサポートは、純粋に歴史的な理由で推奨されません。
出力を繰り返すため、堅牢性の問題がありますfind
。これは非常に悪い考えであり、完全に不要です。スペースまたは特殊文字を含むファイル名でスクリプトが中断されます。望むより:
スクリプトを移植可能にするには、可能であればPOSIXで指定された機能に固執する必要があります。特に-executable
最も重要なfind
ことPOSIX が指定されていません。。代わりに試してみてください-perm +700
。
さらに、移植性領域では、次の順序でa
Sed \<newline>
()を使用するGNU Sedの「追加」コマンドは機能しますが、標準ではありません。
file
ループ内の変数を各ファイルの名前に順番に設定します(for
ファイル名に特殊文字やスペースが含まれていないと仮定すると、変数にfile
次のものが含まれます)。いいえファイル名)、しかし実際には使用変数file
。
Sedコマンドは実行するファイルを提供しないため、標準入力から実行しようとします。したがって、スクリプトを実行すると入力を待ちます。
Sedスクリプト自体が正しくなく、機能するファイル名がないという事実とは無関係です。
/
正規表現(最も一般的なもの)で区切り文字として使用する場合は、正規表現/
でその文字が出てくるすべての項目をバックスラッシュでエスケープする必要があります。コマンドの唯一の部分は正規表現として読み取られ、/\#!/
残りの部分(これで始まる部分bin
)はSedコマンドとして解釈されます。
代わりに、一般的な解決策はそれぞれを交換することです。/
その他最終正規表現の区切り記号より\/
(エスケープされたようです。ただ最後のスラッシュはいいえ脱出しました。 )
一つあるSedのよく知られていない機能、ここでこれを利用することができます。 どのバックスラッシュや改行以外の文字は、スラッシュだけでなく正規表現の区切り文字としても使用できます。したがって、これを/#!\/bin\/bash/
Sedアドレスとして使用する代わりに、同等のアドレスを使用できます。\:#!/bin/bash:
さて、上記のすべてを処理したら、うまくいくスクリプトがありました。おそらくあなたが望むようにならないでしょう。考えるそうする必要がありますが、実際にはそうなります。何かをしなさい。これらのスクリプトは次のとおりです。
#!/bin/bash
find . -type f -perm -700 -exec sed '\:#!/bin/bash:a\
Hello World' {} +
このスクリプトは何をしますか?現在のディレクトリで実行可能ビット(所有者)が設定されているすべてのファイルを繰り返し検索し、これらのファイルごとにファイル全体を印刷し、Hello World
textを含む行の後にテキストを追加します#!/bin/bash
。
sedは実際にはありませんデザイン済みファイルをその場で編集するために使用されます。ストリームエディタです。 GNU Sedではスイッチを使ってファイルを編集できますが、-i
私は次のようにします。標準ツールex
ファイルの編集に使用されます。
しかし、ここには別のものがあります。 Bashスクリプトにその行を追加したい場合は、有効なコマンド名ではないため、Hello World
実際には何もしません。Hello
おそらくあなたが望むもの印刷Bashスクリプトに「Hello World」というテキストを追加するのはecho "Hello World
合理的かもしれません。
今、私たちはあなたのスクリプトが何であるかをより正確に説明したいと思います。しなければならないします。
最終スクリプト
したがって、このスクリプトの仕様のより正確な説明は次のとおりです。
- このスクリプトは、所有者に対して実行可能ビットが設定されている現在のディレクトリ(または再帰的にすべてのサブディレクトリ)ですべての一般ファイルを見つける必要があります。
- これらのファイルごとに、スクリプトはファイルの最初の行が文字列とまったく同じであることを確認する必要があります
#!/bin/bash
。 - 正確な最初の行を持つファイルの場合にのみ、スクリプトはファイル
echo "Hello World"
の最初の行の後に正しいテキストを挿入し、その後に改行文字を挿入する必要があります。 (この変更は標準出力として印刷するのではなくファイルに保存する必要があります。)
以下は、POSIXツールと機能のみを使用して正確な仕様に準拠したスクリプトです。
#!/bin/sh
find . -type f -perm -700 -exec sh -c '
for f
do
head -n 1 "$f" | grep -qFx "#!/bin/bash" &&
printf "%s\n" "1a" "echo \"Hello World\"" . x | ex "$f"
done
' find-sh {} +