shell 查找尚未从一个目录复制到另一个文件树的文件

vmdwslir  于 2023-03-13  发布在  Shell
关注(0)|答案(1)|浏览(132)

考虑一下我将文件从一个磁盘(例如SD卡)复制到给定目录(例如/home/pepa/dir1)的情况
但是后来在Dir1中创建了子目录,并且许多文件被移动到这些子目录。
过了一段时间,我想清理SD,但我想首先确保SD中的所有文件确实存在于dir1或其任何子目录中。我如何检查SD中的所有文件确实存在于dir1或其任何子目录中?
(通过终端中的命令行或特定的linux实用程序)

g52tjvyc

g52tjvyc1#

假设文件数不太大:

#!/bin/bash

sd=$1
dir1=$2

mkmap()(
    if cd "$1"; then
        find -type f -exec sha256sum {} + |\
        sed 's/^\\//'
    fi
)

awk '
    NR==FNR { k=$1; sub(/^[^ ]* ./,""); a[k]=$0 ; next }
    { delete a[$1] }
    END { print "missing files:"; for(i in a) print a[i] }
' <(mkmap "$sd") <(mkmap "$dir1")

mkmap

  • 使用sha256sum来计算树中文件的校验和
  • 使用sed删除sha256sum添加的标记奇数文件名的指示符

然后为每个目录树创建Map并馈送到awk

  • 为SD列表创建校验和到文件名的Map
  • 从校验和出现在DIR1列表中的Map中删除所有条目
  • 对于剩余的Map条目,打印相关的文件名

为清楚起见,省略了错误检查。
对于数量极大的文件,可以生成两个列表,然后生成sort,并馈送到comm

#!/bin/bash

sd=$1
dir1=$2

mkmap()(
    if cd "$1"; then
        find -type f -exec sha256sum {} + |\
        sed 's/^\\//'
    fi
)

map2sums()(
    mkmap "$2" |\
    tee "$1-map" |\
    sed 's/ .*$//' |\
    sort -u > "$1-sums"
)

map2sums sd   "$sd"
map2sums dir1 "$dir1"

comm -23 sd-sums dir1-sums |\
sed 's/^/^/' |\
grep -f - sd-map |\
sed 's/^[^ ]* .//'

rm {sd,dir1}-{map,sums}

map2sums

  • 生成并保存Map
  • 剥离文件名
  • 排序并保存唯一校验和

创建校验和Map和列表。
comm管道:

  • 使用comm输出仅存在于SD列表中的校验和
  • 通过管道连接到sed以将校验和转换为正则表达式
  • 通过管道连接到grep以在SDMap中查找正则表达式
  • 使用sed从Map中剥离校验和并打印相关文件名

然后清除临时文件。
如果你想快点,

AND您只关心DIR1下是否存在与SD下的文件具有相同名称的文件(即,您不关心它们是否包含相同的内容)
ANDSD下文件的基本名称是唯一的
没有太多的文件(即在内存中存储名称列表是可行的)

那么你可以试试这个替代版本:

#!/bin/bash

sd=$1
dir1=$2

mklist()( cd "$1" && find -type f -print0 )

gawk -F/ -v RS='\0' '
    NR==FNR { a[$NF]; next }
    { delete a[$NR] }
    END { for (i in a) print i }
' <(mklist "$sd") <(mklist "$dir1")
  • 生成每个根目录下所有文件的完整路径列表并将其馈送到awk
  • 对于SD列表中的每个路径,将基名存储在Map中
  • 对于DIR1列表中的每个路径,从Map中删除basename
  • 打印剩余的Map条目

脚本可以处理任何法律的名称的文件,但如果名称中包含换行符,则输出将不明确。
注意,与前两个版本不同,如果文件被重命名,这个版本将不会产生合理的输出。例如,给定以下操作序列:

cd /dir1

cp /sd/f1 .
cp /sd/f2 .
cp /ds/f3 .

mv f1 f4

rm f2
mv f3 f2

这个版本将报告/sd/f1/sd/f3丢失(并且认为/sd/f2存在),这可能不是所期望的。

相关问题