你如何区分一个目录只包含特定类型的文件?

Posted

技术标签:

【中文标题】你如何区分一个目录只包含特定类型的文件?【英文标题】:How do you diff a directory for only files of a specific type? 【发布时间】:2010-09-23 04:02:02 【问题描述】:

我对 diff 命令有疑问 如果我想要一个递归目录差异但只针对特定的文件类型,该怎么做?

我尝试使用排除选项,但只能使用一种模式:

$ diff /destination/dir/1 /destination/dir/2 -r -x *.xml

使用该命令我只能排除 xml 文件类型,即使文件夹图像类型中有文件(pnggifjpg)、txtphp

如何仅区分某些文件类型。

【问题讨论】:

***.com/q/10131908/2707864 那么您是要区分特定类型的文件还是排除这些文件的差异?这个问题与描述无关.. 【参考方案1】:

您可以多次指定-x

diff -x '*.foo' -x '*.bar' -x '*.baz' /destination/dir/1 /destination/dir/2

来自info diff 的比较目录部分(在我的系统上,我必须这样做info -f /usr/share/info/diff.info.gz):

要在比较目录时忽略某些文件,请使用 '-x PATTERN' 或 '--exclude=PATTERN' 选项。此选项忽略任何文件 或基本名称与外壳模式 PATTERN 匹配的子目录。 与 shell 不同,文件名开头的句点 匹配模式开头的通配符。你应该附上 引号中的 PATTERN 以便 shell 不会扩展它。例如, 选项 -x '*.[ao]' 忽略名称以 '.a' 或 '.o'。

如果您多次指定此选项,则会累积该选项。为了 例如,使用选项 -x 'RCS' -x '*,v' 会忽略任何文件或 基本名称为“RCS”或以“,v”结尾的子目录。

【讨论】:

我的(ubuntu 10.04)没有这些行。我也试过了,还是不行。我猜这是一个新版本。【参考方案2】:

取自(一个版本的)手册页:

-x PAT  --exclude=PAT
  Exclude files that match PAT.

-X FILE    --exclude-from=FILE
  Exclude files that match any pattern in FILE.

所以看起来-x 在您报告时只接受一种模式,但如果您将所有要排除的模式放在一个文件中(大概每行一个),您可以像这样使用第二个标志:

$ diff /destination/dir/1 /destination/dir/2 -r -X exclude.pats

exclude.pats 在哪里:

*.jpg
*.JPG
*.xml
*.XML
*.png
*.gif

【讨论】:

您可以使用以下命令行在您的文件夹中找到除 扩展名之外的所有文件扩展名:find . -type f -not -name '*.<my-ext>' | xargs -I% basename '%' | awk -F . 'NF > 1 print "*." $NF; NF == 1 print $NF ' | sort | uniq > exclude.pats 我希望我早先注意到 John 的评论,但是在 macOs/bash 上,我找到了一个类似的解决方案来生成具有几种要保留的模式的排除文件:find . -not -name "*.c" -and -not -name "*.h" -and -type f -print0 | xargs -0 basename | grep -E '.*\..+' | sed 's/\./\//g' | xargs basename | xargs printf '*.%s\n' | sort | uniq > X-FILE 我想相信这会有所帮助,也许在 Linux 上也是如此。 (在这个例子中,单个-name "*.[ch]" 是可以的,但它不是很能说明问题)【参考方案3】:

你也可以使用 find 和 -exec 来调用 diff:

cd /destination/dir/1
find . -name *.xml -exec diff  /destination/dir/2/ \;

【讨论】:

【参考方案4】:

缺少补充的 --include ... 。

我们可以做一个解决方法,一个包含所有文件但我们想要包含的文件的排除文件。所以我们创建file1 并查找所有没有我们想要包含的扩展名的文件,sed 捕获文件名并且只是:

diff --exclude-from=file1  PATH1/ PATH2/

例如:

find  PATH1/ -type f | grep --text -vP "php$|html$" | sed 's/.*\///' | sort -u > file1 
diff PATH1/ PATH2/ -rq -X file1 

【讨论】:

超级有用的单线,谢谢。在 Mac OSX 上,grep 略有不同,它变为 find PATH1/ -type f | grep --text -v -e "php$" -e html$" | sed 's/.*\///' | sort -u > file1 diff PATH1/ PATH2/ -rq -X file1【参考方案5】:

我使用以下命令查找DIR1DIR2 之间所有*.tmpl 文件的差异。在我的情况下,这并没有产生任何误报,但它可能对你来说,这取决于你的 DIRS 的内容。

diff --brief DIR1 DIR2 | grep tmpl

【讨论】:

【参考方案6】:

由于缺乏补充的 --include 使得有必要使用这样复杂的启发式模式

*.[A-Zb-ik-uw-z]*

查找(主要是)java 文件!

【讨论】:

【参考方案7】:

如果您想区分来源并保持简单:

diff -rqx "*.a" -x "*.o" -x "*.d" ./PATH1 ./PATH2 | grep "\.cpp " | grep "^Files"

如果要获取仅存在于其中一个路径中的文件,请删除最后一个 grep。

【讨论】:

我喜欢简单 :-) 在德语中将 grep "^Files" 更改为 grep "^Dateien"【参考方案8】:

如果您觉得方便,可以使用以下Makefile。只需运行:“make patch”

#Makefile for patches

#Exlude following file endings
SUFFIX += o
SUFFIX += so
SUFFIX += exe
SUFFIX += pdf
SUFFIX += swp

#Exlude following folders
FOLDER += bin
FOLDER += lib
FOLDER += Image
FOLDER += models

OPTIONS = Naur

patch: 
    rm test.patch
    diff -$(OPTIONS) \
    $(foreach element, $(SUFFIX) , -x '*.$(element)') \
    $(foreach element, $(FOLDER) , -x '$(element)*') \
        org/ new/ > test.patch  

unpatch: 
    rm test.unpatch
    diff -$(OPTIONS) \
    $(foreach element, $(SUFFIX) , -x '*.$(element)') \
    $(foreach element, $(FOLDER) , -x '$(element)*') \
    new/ org/ > test.unpatch

【讨论】:

【参考方案9】:

虽然它不能避免其他文件的实际diff,但如果您的目标是生成补丁文件或类似文件,则可以使用patchutils 包中的filterdiff,例如仅修补您的 .py 更改:

diff -ruNp /path/1 /path/2 | filterdiff -i "*.py" | tee /path/to/file.patch

【讨论】:

以上是关于你如何区分一个目录只包含特定类型的文件?的主要内容,如果未能解决你的问题,请参考以下文章

Bash:检查目录是不是仅包含具有特定后缀的文件

如何获取SVN中文件/文件夹属性的历史记录?

区分碰撞中的精灵

linux查找当前目录下所有子目录特定文件类型需要查找的文件内容

如何查询 NHibernate 的特定类型?

如何区分js数据类型