簡體   English   中英

如何使用 perl 刪除與正則表達式匹配的文件

[英]How can I use perl to delete files matching a regex

由於Makefile錯誤,我的 git 存儲庫中有一些假文件......

$ 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 { /\W\d+\.\d+/ } glob "*") {
    my $cmd1 = "rm $filename";
    `$cmd1`;
}

問題:

  • 我想要一個與 pcre 匹配的刪除命令。
  • 什么是更有效的perl解決方案來刪除與此/\W\d+\.\d+/正則表達式匹配的文件:/\W\d+\.\d+/(例如文件名:'=0.1.1')

獲取更廣泛的文件集,然后過濾任何你想要的

my @files_to_del = grep { /^\W[0-9]+\.[0-9]+/ and not -d } glob "$dir/*"; 

我添加了一個錨點 ( ^ ),以便正則表達式只能匹配以該模式開頭的字符串,否則這可能會破壞預期以外的文件。 重新考慮您到底需要什么。

總而言之(或者看下面的一行

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中的*也可能有一些預選。 特別是,如果=是文字字符(而不是 shell 打印的指示符,請參見腳注) 那么glob "=*"將獲取以它開頭的文件,然后您可以通過grep過濾器傳遞這些文件。

我排除了由-d filetest標識的目錄,因為我們正在尋找文件(並且不要與unlink中關於目錄的一些可怕語言混合,感謝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)

然后在代碼中使用glob "$d/*" 這與上面腳本中的工作方式相同——shift@ARGV中提取第一個元素,如果在命令行上向腳本傳遞了任何內容,或者如果@ARGV為空,則返回undef然后// (已定義-或) 運算符選取字符串q(.)


如果ls已使用ls -F別名,則前導=可能是文件類型的“指示符”,可以通過運行帶有抑制別名的ls來檢查什么,一種方法是\ls (或檢查alias ls )。

如果是這樣, =代表它是一個套接字,可以通過-S filetest 測試 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 /\A\W\d+\.\d+/a' | xargs rm

而且,當我這樣做時,我為沒有在grep中使用擴展模式做一些更簡單的事情而感到內疚:

ls | grep -E '^\W\d+\.\d+' | xargs rm

最終我會遇到一個有目錄的問題,所以我需要更加小心文件列表:

find . -type f  -maxdepth 1 | grep -E '^\./\W\d+\.\d+' | xargs rm

或者我也需要允許rm刪除目錄:

ls | grep -E '^\W\d+\.\d+' | xargs rm -r

給你 go。

unlink( grep { /\W\d+\.\d+/ && !-d } glob( "*" ) );

這與文件名匹配,但不包括目錄。

要刪除與此匹配的文件名: /\W\d+\.\d+/ pcre ,請使用以下單行...

1> $fn是一個文件名...我也刪除了my關鍵字,因為單行代碼不必擔心perl 詞法范圍

perl -e 'foreach $fn (grep { /\W\d+\.\d+/ } glob "*") {$cmd1="rm $fn";`$cmd1`;}'

2> 或者正如Andy Lester 所回答的那樣,也許他的回答是我們能做到的最有效的……

perl -e 'unlink(grep { /\W\d+\.\d+/ } glob "*");'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM