我的系统中有大量文件,每个文件都有一个对应的文件名。例如,
test.pdf
有一个test-project.zip
test2.pdf
有一个test2-project.zip
test.pdf
和test2.pdf
是原始文件,而test-project.zip
和test2-project.zip
由我的脚本生成。
我需要查明我的所有原始文件是否'filename'-project.zip
与原始文件有对应关系。
我可以用
find /project/ -name "*.pdf" | wc -l
find /project/ -name "*-project.zip" | wc -l
查明数字是否匹配,但我需要知道哪个文件没有对应的文件。
有人能帮我吗?非常感谢!
答案1
快速脚本,根据您的需要进行调整:
#!/usr/bin/env bash
find /project/ -name '*.pdf' -print0 | while read -d $'\0' i; do
if [ ! -e "${i/%.pdf/-project.zip}" ]; then
echo "${i/%.pdf/-project.zip} doesn't exist!"
fi
done
exit 0
-d $'\0'
将 的分隔符设置为read
nullbyte,而-print0
相当于find
,因此这应该可以防止名称中带有空格和换行符的文件(在这种情况下显然无关紧要,但一般情况下很有用)。将变量末尾的${i/%.pdf/-project.zip}
替换为。除此之外,这些都是标准的 shell 脚本内容。.pdf
$i
-project.zip
如果你想进一步缩短它,你也可以使用
[ -e "${i/%.pdf/-project.zip}" ] || echo "${i/%.pdf/-project.zip} doesn't exist!"
...而不是语句if
。我认为,if
如果您使用多条短行,则更容易使用(您可以使用函数来解决这个问题,但此时与使用相比,您不会节省任何空间if
)。
假设您有 bash 4+(您可能有;您可以使用 检查bash --version
),您可以使用 globstar 选项代替find
:
#!/usr/bin/env bash
shopt -s globstar
for f in /project/**/*.pdf; do
if [ ! -e "${f/%.pdf/-project.zip}" ]; then
echo "${f/%.pdf/-project.zip} doesn't exist!"
fi
done
exit 0
它的优点是纯 bash,所以速度应该更快(但只有在至少数百个文件时才会明显更快)。
答案2
有两种方法可以实现这一点。一种方法是使用 Bash 单行命令,它会为每个匹配的文件生成至少一个(可能两个)进程:
[me@box] $ for file in `find -name '*.pdf' -exec perl -le'$f=shift(); $f =~ s@\.pdf$@@; print $f' {} \;`; do (TESTFILE="$file-project.zip"; if [ ! -f $TESTFILE ]; then echo "missing $TESTFILE"; fi); done
因为这足以让任何人大吃一惊,这里有一个 Perl 脚本可以完成同样的工作,而且比任何 Bash 脚本都要合理得多:
#!/usr/bin/env perl
use strict;
my $path = shift() || die "$0 requires a path argument\n";
my @files = `find "$path" -name '*.pdf'`;
foreach my $file (@files) {
chomp $file;
my $zip = $file;
$zip =~ s@\[email protected]@;
next if -f $zip;
print "missing $zip\n";
};
将其复制到例如“find-missing.pl”中,然后调用find-missing.pl /project/
。