简体   繁体   English

删除不包含特定字符串的文件

[英]Remove files not containing a specific string

I want to find the files not containing a specific string (in a directory and its sub-directories) and remove those files.我想找到不包含特定字符串的文件(在目录及其子目录中)并删除这些文件。 How I can do this?我该怎么做?

The following will work:以下将起作用:

find . -type f -print0 | xargs --null grep -Z -L 'my string' | xargs --null rm

This will firstly use find to print the names of all the files in the current directory and any subdirectories.这将首先使用 find 打印当前目录和任何子目录中所有文件的名称。 These names are printed with a null terminator rather than the usual newline separator (try piping the output to od -c to see the effect of the -print0 argument.这些名称用空终止符打印,而不是通常的换行符(尝试将输出传送到od -c以查看-print0参数的效果。

Then the --null parameter to xargs tells it to accept null-terminated inputs.然后xargs--null参数告诉它接受以 null 结尾的输入。 xargs will then call grep on a list of filenames.然后xargs将对文件名列表调用grep

The -Z argument to grep works like the -print0 argument to find , so grep will print out its results null-terminated (which is why the final call to xargs needs a --null option too).-Z参数grep作品像-print0参数find ,这样的grep会打印出它的结果空值终止的(这就是为什么到最后调用xargs需要--null选项也是如此)。 The -L argument to grep causes grep to print the filenames of those files on its command line (that xargs has added) which don't match the regular expression: grep-L参数导致grep在其命令行上打印那些与正则表达式匹配的文件的文件名( xargs已添加):

my string我的字符串

If you want simple matching without regular expression magic then add the -F option.如果您想要没有正则表达式魔法的简单匹配,请添加-F选项。 If you want more powerful regular expressions then give a -E argument.如果你想要更强大的正则表达式,那么给一个-E参数。 It's a good habit to use single quotes rather than double quotes as this protects you against any shell magic being applied to the string (such as variable substitution)使用单引号而不是双引号是一个好习惯,因为这可以保护您免受应用于字符串的任何 shell 魔法(例如变量替换)

Finally you call xargs again to get rid of all the files that you've found with the previous calls.最后,您再次调用xargs以删除您在先前调用中找到的所有文件。

The problem with calling grep directly from the find command with the -exec argument is that grep then gets invoked once per file rather than once for a whole batch of files as xargs does.直接从带有-exec参数的find命令调用grep的问题在于, grep然后每个文件被调用一次,而不是像xargs那样对整批文件调用一次。 This is much faster if you have lots of files.这是更快,如果你有大量的文件。 Also don't be tempted to do stuff like:也不要试图做这样的事情:

rm $(some command that produces lots of filenames)

It's always better to pass it to xargs as this knows the maximum command-line limits and will call rm multiple times each time with as many arguments as it can.将它传递给xargs总是更好,因为它知道最大命令行限制,并且每次都会使用尽可能多的参数多次调用rm

Note that this solution would have been simpler without the need to cope with files containing white space and new lines.请注意,此解决方案会更简单,而无需处理包含空格和新行的文件。

Alternatively或者

grep -r -L -Z 'my string' . | xargs --null rm

will work too (and is shorter).也会起作用(并且更短)。 The -r argument to grep causes it to read all files in the directory and recursively descend into any subdirectories). grep-r参数使其读取目录中的所有文件并递归下降到任何子目录)。 Use the find ... approach if you want to do some other tests on the files as well (such as age or permissions).如果您还想对文件进行一些其他测试(例如年龄或权限),请使用find ...方法。

Note that any of the single letter arguments, with a single dash introducer, can be grouped together (for instance as -rLZ ).请注意,任何带有单个破折号介绍-rLZ的单字母参数都可以组合在一起(例如-rLZ )。 But note also that find does not use the same conventions and has multi-letter arguments introduced with a single dash.但还要注意find不使用相同的约定,并且使用单个破折号引入了多字母参数。 This is for historical reasons and hasn't ever been fixed because it would have broken too many scripts.这是出于历史原因,从未修复过,因为它会破坏太多脚本。

GNU grep and bash. GNU grep 和 bash。

grep -rLZ "$str" . | while IFS= read -rd '' x; do rm "$x"; done

Use a find solution if portability is needed.如果需要可移植性,请使用find解决方案。 This is slightly faster.这稍微快一点。

EDIT: This is how you SHOULD NOT do this!编辑:这是你不应该这样做的方式! Reason is given here .原因在这里给出。 Thanks to @ormaaj for pointing it out!感谢@ormaaj 指出!

find . -type f | grep -v "exclude string" | xargs rm

Note: grep pattern will match against full file path from current directory (see find . -type f output)注意: grep模式将匹配当前目录中的完整文件路径(请参阅find . -type f输出)

One possibility is一种可能性是

find . -type f '!' -exec grep -q "my string" {} \; -exec echo rm {} \;

You can remove the echo if the output of this preview looks correct.如果此预览的输出看起来正确,您可以删除echo

The equivalent with -delete is-delete等效的是

find . -type f '!' -exec grep -q "user_id" {} \\; -delete

but then you don't get the nice preview option.但是这样你就没有很好的预览选项。

I can think of a few ways to approach this.我可以想到几种方法来解决这个问题。 Here's one: find and grep to generate a list of files with no match, and then xargs rm them.这是一个: find 和 grep 生成不匹配的文件列表,然后 xargs rm 它们。

find yourdir -type f -exec grep -F -L 'yourstring' '{}' + | xargs -d '\n' rm

This assumes GNU tools (grep -L and xargs -d are non-portable) and of course no filenames with newlines in them.这假设 GNU 工具(grep -L 和 xargs -d 是不可移植的)并且当然没有包含换行符的文件名。 It has the advantage of not running grep and rm once per file, so it'll be reasonably fast.它的优点是不对每个文件运行 grep 和 rm 一次,因此速度相当快。 I recommend testing it with "echo" in place of "rm" just to make sure it picks the right files before you unleash the destruction.我建议用“echo”代替“rm”来测试它,以确保它在你释放破坏之前选择正确的文件。

To remove files not containing a specific string:要删除不包含特定字符串的文件:

Bash:重击:

To use them, enable the extglob shell option as follows:要使用它们,请按如下方式启用 extglob shell 选项:

shopt -s extglob

And just remove all files that don't have the string "fix":只需删除所有没有字符串“fix”的文件:

rm !(*fix*)

If you want to don't delete all the files that don't have the names "fix" and "class":如果您不想删除所有没有名称“fix”和“class”的文件:

rm !(*fix*|*class*)

Zsh: Zsh:

To use them, enable the extended glob zsh shell option as follows:要使用它们,请启用扩展的 glob zsh shell 选项,如下所示:

setopt extended_glob

Remove all files that don't have the string, in this example "fix":删除所有没有字符串的文件,在本例中为“修复”:

rm -- ^*fix*

If you want to don't delete all the files that don't have the names "fix" and "class":如果您不想删除所有没有名称“fix”和“class”的文件:

rm -- ^(*fix*|*class*)

It's possible to use it for extensions, you only need to change the regex: ( .zip) , ( .doc), etc.可以将它用于扩展,您只需要更改正则表达式:( .zip) 、( .doc) 等。

Here are the sources:以下是来源:

https://www.tecmint.com/delete-all-files-in-directory-except-one-few-file-extensions/ https://www.tecmint.com/delete-all-files-in-directory-except-one-few-file-extensions/

https://codeday.me/es/qa/20190819/1296122.html https://codeday.me/es/qa/20190819/1296122.html

This worked for me, you can remove the -f if you're okay with deleting directories.这对我有用,如果您可以删除目录,则可以删除 -f。

myString="keepThis"
for x in `find  ./`
    do if [[ -f $x && ! $x =~ $myString ]]
        then rm $x
    fi
done

Another solution (although not as fast).另一种解决方案(虽然没有那么快)。 The top solution didn't work in my case because the string I needed to use in place of 'my string' has special characters.最佳解决方案在我的案例中不起作用,因为我需要用来代替“我的字符串”的字符串具有特殊字符。

find -type f ! -name "*my string*" -exec rm {} \; -print

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 查找子目录并删除不包含特定字符串LINUX的文件 - Find subdirectory and remove files not containing a specific string LINUX 列出ls -1包含特定字符串并忽略特定字符串的文件 - List files with ls -1 containing specific string AND ignoring specific string 如何在Linux中名称包含特定字符串的文件中搜索字符串? - How to search for a string in files with name containing a specific string in linux? 如何使用sed命令从文件中删除包含特定字符串的行 - How to remove a line containing specific string from file with sed command 从目录中的所有文件中删除包含字符串的行 - Remove lines containing a string from all files in directory 删除所有包含特定字符串的文件 - Bash - Remove all files contain specific string - Bash 如何更改 linux 上包含特定字符串的所有目录/文件的名称 - how to change names of all directories / files containing a specific string on linux 仅打开包含特定字符串的文件,然后在Linux命令行上进行替换 - Open only files containing a specific string and then replace on Linux command line 如何在 Linux 上查找包含特定文本(字符串)的所有文件? - How to find all files containing specific text (string) on Linux? 如何从文件夹中的所有文件中删除带有特定字符串的行 - How to remove from all files in folder the lines with specific string
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM