如何使用perl删除与regex匹配的文件



由于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过滤器传递这些文件。

我排除了由-dfiletest标识的目录,因为我们正在寻找文件(由于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 "*");'

相关内容

  • 没有找到相关文章

最新更新