从find命令输出中删除路径


29

我有一个bash脚本,用于将代码从Beta环境部署到生产环境,但是目前我不得不手动将文件列表添加到txt文件中,有时我会错过一些。基本上,我的部署脚本通过cat / loops复制文件。(也可以导出/导入数据库,但这不相关..lol)

无论如何,我想使用该find命令生成最近14天内修改的文件列表。问题是我需要删除路径./才能使部署脚本正常工作。

这是find命令用法的示例:

找 。-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 2012年

有效点,但是在部署之前,请仔细检查deploy.txt并删除所有需要修复的内容
Mikey1980,2012年

1
也许在--dry-run模式下运行rsync 并将其输出到文件以供查看?
Zoredache

Answers:


36

您可以将-printf命令行选项与一起使用%f,仅打印文件名,而不包含任何目录信息

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

或者您可以使用sed删除./

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

相信你必须逃避现实/.
EEAA 2012年

5
当您|用作分隔符时不行。
user9517支持GoFundMonica 2012年

3
使用%f将删除所有目录,而不仅仅是./。如果返回的任何文件find位于子目录中,这将破坏他的部署脚本。
James Sneeringer 2012年

2
@Iain你确实需要逃脱.。也许最好使用行开始锚:s|^\./||
James O'Gorman 2012年

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特别询问了如何删除它,因为这会导致他的部署脚本出现问题。当然,也许会有更好的方法来完成他需要做的事情,但这是一个远远超出要求范围的难题。
James Sneeringer

7

为什么需要剥离./?在路径中有效。所以

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

没关系!

但是,如果您想删除find中的目录名,则可以使用%Parg来-printf

男子发现(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并不是我真正的
堡垒

2
再看一遍,有例子。
Zoredache

同意-只需尝试一下,运行find和sed的组合不会对您造成任何伤害。
EEAA 2012年

3

“ find -printf”解决方案在FreeBSD上不起作用,因为find没有这样的选择。在这种情况下,AWK可以提供帮助。它返回姓氏($ NF),因此可以在任何深度使用。

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

PS:摘自D.Tansley的《 Linux和Unix Shell编程》一书


2

如果我对问题的理解正确,一种快速的解决方案是cutfind命令的输出上使用:

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

这会将结果的每一行中的第一个字符去除为字符(在您的情况下./)。可能不是最佳解决方案,但可以在您的情况下使用。



1

我不知道我们在谈论哪种文件名,但是任何带有空格或换行符的文件都会使大多数解决方案处于危险之中。

我的建议是使用shell的参数扩展从每个文件名中去除字符:

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

如果您真的很喜欢管道,则可以使用带有xargs的“安全”定界符(如null)来接收每个文件名:

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

请记住,此输出不是以空分隔的,因此尽管足够进行眼球检查,但除非您对源非常有信心,否则这些解决方案都不会产生可安全用于自动化的deploy.txt文件。文件名。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.