web-dev-qa-db-ja.com

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

ベータ環境から本番環境にコードをデプロイするための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スクリプトを使用してこれを実現する方法はありますか?

ありがとう!

31
Mikey1980

-printfコマンドラインオプションと%fディレクトリ情報なしでファイル名だけを印刷します

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

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

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

./は無害でなければなりません。ほとんどのプログラムは/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は、見つかった各ファイルの完全なパスから、コマンドラインで指定されたパスを除いて、最初のスラッシュまでを返します。これにより、ディレクトリ構造内のサブディレクトリが保持されます。

12

./を取り除く必要があるのはなぜですか?パスに含めることは有効です。そう

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

大丈夫です!

しかし、findでディレクトリ名を取り除きたい場合は、%P引数を-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
7
TrueY

「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」の本から引用

5
user221341

さてあなたはいくつかのオプションがあります。 -printfオプションを使用してファイル名のみを出力するか、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/^\.\///'
3
Zoredache

質問を正しく理解していれば、cutコマンドの出力でfindを使用するのが簡単な解決策です。

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

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

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

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

私たちが話しているファイル名の種類はわかりませんが、スペースや改行が含まれていると、ほとんどの解決策が危険にさらされます。

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

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

これの出力は[〜#〜] not [〜#〜] null区切りであることを覚えておいてください。目視チェックには十分かもしれませんが、これらのソリューションはどれもdeploy.txtファイルを生成しませんソースファイル名に自信がない場合は、自動化に使用しても安全です。

1
ghoti