由于Makefile
错误,我的git repo中有一些假文件。。。
$ ls
=0.1.1 =4.8.0 LICENSE
=0.5.3 =5.2.0 Makefile
=0.6.1 =7.1.0 pyproject.toml
=0.6.1, all_commands.txt README_git_workflow.md
=0.8.1 CHANGES.md README.md
=1.2.0 ciscoconfparse/ requirements.txt
=1.7.0 configs/ sphinx-doc/
=2.0 CONTRIBUTING.md tests/
=2.2.0 deploy_docs.py tutorial/
=22.2.0 dev_tools/ utils/
=22.8.0 do.py
=2.7.0 examples/
$
我试过了,但似乎有一些更有效的方法来完成这项任务。。。
# glob "*" will list all files globbed against "*"
foreach my $filename (grep { /Wd+.d+/ } glob "*") {
my $cmd1 = "rm $filename";
`$cmd1`;
}
问题:
- 我想要一个与pcre匹配的remove命令
- 什么是更有效的
perl
解决方案来删除与此perl正则表达式匹配的文件:/Wd+.d+/
(示例文件名:'=0.1.1'(
获取更广泛的文件集,然后通过您想要的进行过滤
my @files_to_del = grep { /^W[0-9]+.[0-9]+/ and not -d } glob "$dir/*";
我添加了一个锚点(^
(,这样regex就只能将以开头的字符串与该模式匹配,否则这可能会破坏预期之外的文件。重新考虑你到底需要什么。
总之,也许(或参见†下方的一行(
use warnings;
use strict;
use feature 'say';
use File::Glob ':bsd_glob'; # for better glob()
use Cwd qw(cwd); # current-working-directory
my $dir = shift // cwd; # cwd by default, or from input
my $re = qr/^W[0-9]+.[0-9]+/;
my @files_to_del = grep { /$re/ and not -d } glob "$dir/*";
say for @files_to_del; # please inspect first
#unlink or warn "Can't unlink $_: $!" for @files_to_del;
其中glob
中的*
也可能具有一些预选择(如果合适的话(。特别是,如果=
是一个文字字符(而不是外壳打印的指示符,请参阅脚注(⏹,则glob "=*"
将从它开始获取文件,然后您可以通过grep
过滤器传递这些文件。
我排除了由-d
filetest标识的目录,因为我们正在寻找文件(由于brian d foy
的评论,为了避免与一些关于取消链接的目录的可怕语言混合(。
如果您需要扫描子目录并对它们执行同样的操作,也许是递归的——这里的情况似乎不是这样?——那么我们可以在File::Find::find
(或File::Find::Rule
或其他(中使用该逻辑。
或者以任何其他方式读取目录(opendir
+readdir
,像Path::Tiny
这样的库(,并进行筛选。
†或者,一个快速的一行。。。打印(检查(即将被吹走的
perl -wE'say for grep { /^W[0-9]+.[0-9]+/ and not -d } glob "*"'
然后删除他们的
perl -wE'unlink or warn "$_: $!" for grep /^W[0-9]+.[0-9]+/ && !-d, glob "*"'
(我切换到了更紧凑的语法。没有必要(
如果您希望能够将目录传递给它(可选,或在当前目录中工作(,则执行
perl -wE'$d = shift//q(.); ...' dirpath (relative path fine. optional)
然后在代码中使用CCD_ 17。这与上面的脚本中的工作方式相同——shift从@ARGV
中提取第一个元素,如果有任何东西在命令行上传递给脚本,或者如果@ARGV
为空,它将返回undef
,然后//
(定义的或(运算符将提取字符串q(.)
。
⏹前导CCD_;指示器";如果ls
已被ls -F
别名,则可以通过使用抑制的别名运行ls
来检查什么,一种方式是ls
(或检查alias ls
(。
如果是这样的话,=
代表它是一个套接字,可以通过-S
文件测试Perl中的内容。
然后,可能需要将所提出的正则表达式中的W
更改为W?
,以允许在数字之前没有非单词字符,同时对套接字进行测试。像
my $re = qr/^W? [0-9]+ . [0-9]+/x;
my @files_to_del = grep { /$re/ and -S } glob "$dir/*";
为什么不只是:
$ rm =*
有时,shell命令是最好的选择。
在这些情况下,我使用perl
只过滤文件列表:
ls | perl -ne 'print if /AWd+.d+/a' | xargs rm
而且,当我这样做的时候,我为没有用grep
:中的扩展模式做一些更简单的事情而感到内疚
ls | grep -E '^Wd+.d+' | xargs rm
最终,我会遇到一个有目录的问题,所以我需要对文件列表更加小心:
find . -type f -maxdepth 1 | grep -E '^./Wd+.d+' | xargs rm
或者我需要允许rm
也删除目录,如果我想要的话:
ls | grep -E '^Wd+.d+' | xargs rm -r
开始吧。
unlink( grep { /Wd+.d+/ && !-d } glob( "*" ) );
这与文件名匹配,但不包括目录。
要删除与此匹配的文件名:/Wd+.d+/
pcre,请使用以下一行。。。
1>$fn
是一个文件名。。。我还删除了my
关键字,因为一行代码不必担心perl词法范围:
perl -e 'foreach $fn (grep { /Wd+.d+/ } glob "*") {$cmd1="rm $fn";`$cmd1`;}'
2>或者正如Andy Lester所回应的,也许他的答案是我们所能做到的最有效的…
perl -e 'unlink(grep { /Wd+.d+/ } glob "*");'