findコマンドの出力からパスを削除する


29

ベータ環境から本番環境にコードを展開するためのbashスクリプトがありますが、現在はファイルのリストを手動でtxtファイルに追加する必要があり、いつかは見逃します。基本的に、私の展開スクリプトはファイルをコピーするcat / loopsです。(dbもエクスポート/インポートしますが、関係ありません..lol)

とにかく、このfindコマンドを使用して、過去14日間に変更されたファイルのリストを生成したいと思います。問題は./、展開スクリプトが機能するためにパスを取り除く必要があることです。

findコマンドの使用例は次のとおりです。

見つける。-type f -mtime -14> deploy.txt

これがdeploy.txt、私の展開スクリプトに含まれる行です。

for i in `cat deploy.txt`; do cp -i /home/user/beta/public_html/$i /home/user/public_html/$i; done

bashスクリプトを使用してこれを達成する方法はありますか?

ありがとう!


3
このためにrsyncを使用できない理由はありますか?車輪を再発明して三角形にしようとしているように聞こえます。
ThatGraemeGuy

ただし、有効なポイントはデプロイ前にdeploy.txtがレビューされ、修正が必要なものはすべて削除されます
Mikey1980

1
たぶん--dry-runモードでrsyncを実行し、レビューのためにファイルに出力しますか?
ゾレダチェ

回答:


36

-printfコマンドラインオプションを使用して、%fディレクトリ情報なしでファイル名のみを印刷できます。

find . -type f -mtime -14 -printf '%f\n' > deploy.txt

または、sedを使用して./を削除することもできます

find . -type f -mtime -14 | sed 's|^./||' >deploy.txt

私はあなたが逃げなければならないと信じています/.
EEAA

5
|区切り文字として使用するときではありません。
user9517はGoFundMonicaをサポートしています12年

3
を使用%fすると、だけでなくすべてのディレクトリが削除されます./。によって返されたファイルのいずれかがfindサブディレクトリにある場合、これにより展開スクリプトが破損します。
ジェームズ・スニーリンガー

2
@Iain .ただし、エスケープする必要があります。:ライン開始アンカーを使用すると、おそらく最高s|^\./||
ジェームズO'Gorman

12
%P代わりに使用します%f。これは、コマンドラインで指定されたパスを単にカットオフします。
TrueY

11

./無害にする必要があります。ほとんどのプログラムは扱います/foo/bar/foo/./bar同等として。あまり見栄えが良くないことは承知していますが、あなたが投稿した内容を基にすると、スクリプトが失敗する理由はわかりません。

あなたが本当にそれを取り除きたいなら、sedおそらく最もクリーンな方法です:

find . -type d -mtime 14 | sed -e 's,^\./,,' > deploy.txt

GNU findを使用するシステム(たとえば、ほとんどのLinuxシステム)を使用している場合は、次のコマンドを使用してワンショットで実行できますfind -printf

find . -type d -mtime 14 -printf "%P\n" > deploy.txt

%Pリターンは、各ファイルの完全なパスが見つかり、マイナスのパスはアップにして最初のスラッシュを含めて、コマンドラインで指定されました。これにより、ディレクトリ構造内のサブディレクトリが保持されます。


1
./プレフィックスは、実際の機能です。これがないと、ダッシュで始まるファイル名など、他のコマンドへのパイプ出力が正しく機能しません。
トリプリー

1
@tripleee-私はそれの有用性を理解していますが、OPは彼の展開スクリプトに問題を引き起こしているので、それを取り除く方法を具体的に尋ねました。確かに、彼がする必要があることをするより良い方法があるかもしれませんが、それは尋ねられたものの範囲をはるかに超えたウサギの穴です。
ジェームズ・スニーリンガー

7

なぜあなたはストリップする必要があり./ますか?パスに含めることは有効です。そう

cp -i dir1/./somefile dir2/./somefile

大丈夫です!

ただし、findでディレクトリ名を削除する場合は、%Pargを使用できます-printf

man find(1)のコメント:

         %P     File's name with the name of the  command  line  argument
                 under which it was found removed.

$ find other -maxdepth 1
other
other/CVS
other/bin
other/lib
other/doc
other/gdbinit
$ find other -maxdepth 1 -printf "%P\n"

CVS
bin
lib
doc
gdbinit

最初の空行に注意してください!避けたい場合は-mindepth 1

$ find other -mindepth 1 -maxdepth 1 -printf "%P\n"
CVS
bin
lib
doc
gdbinit

3

さて、いくつかのオプションがあります。-printffindでオプションを使用してファイル名のみを印刷するか、sedのようなツールを使用して./

# simply print out the filename, will break if you have sub-directories.
find . -mtime -14 -printf '%f\n'

# strip a leading ./
find .  -mtime -14 | sed -e 's/^\.\///'

その使用方法の例を教えてください。申し訳ありませんが、Linuxは本当に私の砦ではありません
Mikey1980

2
もう一度見てください、例があります。
ゾレダチェ

同意-試してみてください。findとsedを組み合わせて実行しているものを傷つけることはありません。
EEAA

3

「find -printf」ソリューションは、findにそのようなオプションがないため、FreeBSDでは機能しません。この場合、AWKが役立ちます。姓($ NF)を返すため、どの深さでも機能します。

find /usr/local/etc/rc.d -type f | awk -F/ '{print $NF}'

PS:D.Tansley「Linux and Unix shell programming」の本から取られた


2

私が質問を正しく理解していれば、簡単な解決策cutfindコマンドの出力で使用しています:

$> find . -type f -mtime -14 | cut -b 3- > deploy.txt

これは、結果の各行から最初の文字を取り除きます(あなたの場合./)。おそらく最善の解決策ではありませんが、シナリオで機能します。


1

sed この種のものに最適です。

$ find . -type f -mtime -14 find . | sed 's/^\.\///' > deploy.txt

1

私たちがどのようなファイル名について話しているのかわかりませんが、スペースや改行を含むものはほとんどのソリューションを危険にさらします。

私の提案は、シェルのパラメーター拡張を使用して、各ファイル名から文字を削除することです。

find . -mtime -14 -exec sh -c 'printf "${0#./}\n"' {} \; >deploy.txt

本当にパイプが好きなら、nullのような「安全な」区切り文字を使用して、xargsで各ファイル名を受け取ることができます。

find . -mtime -14 -print0 | xargs -0 -n 1 sh -c 'printf "${0#./}\n"' >deploy.txt

これの出力があることに注意してくださいしないでヌル区切り、それが眼球のチェックには十分かもしれないが、あなたのソースについて非常に確信していない限り、これらのソリューションのいずれも、自動化のために使用しても安全であるdeploy.txtファイルを生成しませんファイル名。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.