在linux中,如何仅通过文件名比较两个目录并获取不匹配的结果列表

ape*_*ace 2 linux bash comparison diff list

我想知道如何仅通过文件名(忽略扩展名)来比较两个目录(不递归)以获得差异.例如,如果我有列表A和B,我想知道A中存在什么而不是B.

我目前正在处理一些图像.在一个目录中,我有扩展名为.tiff的源文件,在另一个目录中,我处理了扩展名为.png的文件.两个目录中的文件名相同,但只有扩展名不同(例如,一个文件在目录A中命名为foo.tiff,在目录B中命名为foo.png).

我正在尝试查找尚未处理的文件.

谢谢!

Joh*_*024 5

首先让我们创建一个辅助函数:

getfiles() { find "$1" -maxdepth 1 -type f -exec bash -c 'for f in "$@"; do basename "${f%.*}"; done' "" {} + | sort; }
Run Code Online (Sandbox Code Playgroud)

如果运行getfiles dirname,它将返回该目录中的文件的排序列表,而不包含目录的名称且没有任何扩展名.该-maxdepth 1选项意味着find不会递归搜索.

现在,让我们比较文件目录AB:

diff <(getfiles A) <(getfiles B)
Run Code Online (Sandbox Code Playgroud)

输出采用通常的diff格式.由于可以使用任何diff的常规选项,因此输出格式非常灵活.

这里是一个样本目录AB,各自具有一个文件,其他不具备:

$ ls */
A/:
bar.png  foo.png  qux.png

B/:
bar.tiff  baz.tiff  foo.tiff
Run Code Online (Sandbox Code Playgroud)

输出:

$ diff <(getfiles A) <(getfiles B)
1a2
> baz
3d3
< qux
Run Code Online (Sandbox Code Playgroud)

输出正确地标识(a)B具有baz不存在的文件A和(b)A具有qux不存在的文件B.

替代产出

假设我们只是想进行片面比较并找到哪些文件B也不在A.在这种情况下,grep可以使用:

$ grep -vxFf <(getfiles A) <(getfiles B)
baz
Run Code Online (Sandbox Code Playgroud)

这里使用的选项是:

  • -v告诉grep我们排除匹配的行

  • -x告诉我grep只匹配整行

  • -F告诉grep我们模式是固定的字符串,而不是正则表达式.

  • -f告诉grep从文件中获取模式列表,或者在这种情况下,获取类似文件的对象<(getfiles A).

包含空格的文件和目录名称的示例

考虑这些文件:

$ ls */
A A/:
1 bar.png  1 foo.png  1 qux.png

B B/:
1 bar.tiff  1 baz.tiff  1 foo.tiff
Run Code Online (Sandbox Code Playgroud)

输出:

$ diff <(getfiles 'A A') <(getfiles 'B B')
1a2
> 1 baz
3d3
< 1 qux
Run Code Online (Sandbox Code Playgroud)

要么,

$ grep -vxFf <(getfiles 'A A') <(getfiles 'B B')
1 baz
Run Code Online (Sandbox Code Playgroud)

局限性

如果您的任何文件名中包含换行符,则会产生不正确的结果.至少对于grep表格,这可以扩展到更一般的情况.


vvc*_*hik 0

如果我理解正确,您需要执行以下脚本:

#/bin/bash
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
folder1="/home/vagrant/1 b"
folder2="/home/vagrant/2 a"
ext1="tiff"
ext2="png"


for fullfile in ${folder1}/*.$ext1
do
        #echo "$fullfile fullfile"
        filename=$(basename "$fullfile")
        #echo "$filename file"
        extension="${filename##*.}"
        #echo "$extension ext"
        cleanfilename="${filename%.*}"
        #echo "$cleanfilename base"
        if ! [ -a "${folder2}/$cleanfilename.$ext2" ]
        then
                echo $fullfile
        fi
done
IFS=$SAVEIFS
Run Code Online (Sandbox Code Playgroud)

它显示第一个文件夹中存在但第二个文件夹中不存在的文件。像这样:

admin$ mkdir 1
admin$ mkdir 2
admin$ touch 1/1.tiff
admin$ touch 1/2.tiff
admin$ touch 1/3.tiff
admin$ touch 2/1.png
admin$ touch 2/2.png
admin$ vim diff.sh
admin$ chmod +x diff.sh 
admin$ ./diff.sh 
/Users/admin/1/3.tiff
Run Code Online (Sandbox Code Playgroud)