简体   繁体   中英

Remove all files contain specific string - Bash

I have these bad data

AWS-Console.pngcrop-AWS-Console.png                                                                                    
Alimofire.pngcrop-Alimofire.png                                                                                        
Amazon-ECR-.pngcrop-Amazon-ECR-.png                                                                                    
Amazon-ECS.pngcrop-Amazon-ECS.png                                                                                      
Amazon-RDS.pngcrop-Amazon-RDS.png                                                                                      
Angular.pngcrop-Angular.png                                                                                            
AngularJS.pngcrop-AngularJS.png 
.... 1000 more

I'm trying to delete them

I've tried

ls public/assets/fe/img/skill/ | grep crop | rm -rf *crop*
ls public/assets/fe/img/skill/ | grep crop | rm -rf
rm -rf $(ls public/assets/fe/img/skill/ | grep crop)

None of them work...

rm can handle the glob expressions that ls handles:

rm public/assets/fe/img/skill/*crop*

Use the find command instead

find . -name "*crop*" -type f -exec rm -i {} \;
  • -type f will specify to search file only and avoid directories
  • -exec requires the command input to end with \; , the {} being substitute by the result of the command
  • the -i will ask you to confirm; remove it once sure what you do.
  • advice display the result beforehand with -print in place of -exec...

     find. -name "*crop*" -type f -print

More here where your question would find more accurate answers

The main problem in your commands is the missing path in the output of the ls command.

ls public/assets/fe/img/skill/ | grep crop ls public/assets/fe/img/skill/ | grep crop will retur eg AWS-Console.pngcrop-AWS-Console.png which is passed to rm . But rm AWS-Console.pngcrop-AWS-Console.png fails because there is no such file in the current directory. It should be rm public/assets/fe/img/skill/AWS-Console.pngcrop-AWS-Console.png instead.

Adding -d to the ls command should do the trick:

ls -d public/assets/fe/img/skill/ | grep crop | rm -rf
rm -rf $(ls -d public/assets/fe/img/skill/ | grep crop)

As pointed out in other answers, other solutions exist, including:

rm public/assets/fe/img/skill/*crop*
find public/assets/fe/img/skill/ -name "*crop*" -type f -exec rm -i {} \;

If it's a really large number of files (apparently wasn't in your case), xargs can speed up the process . This applies for a lot of things you might want to read from a pipe.

 find . -name "*crop*" -type f | xargs rm

The main advantage of using find here is that it's an easy way to ignore directories. If that's not an issue, let the OS handle all that.

printf "%s\n" public/assets/fe/img/skill/*crop* | xargs rm

If you need to be able to pick up files in subdirectories -

shopt -s globstar # double asterisks not include arbitrary preceding paths
printf "%s\n" public/assets/fe/img/skill/**crop* | xargs rm

You might want to look over the list first, though.

printf "%s\n" public/assets/fe/img/skill/*crop* >crop.lst 
# check the list - vi, grep, whatever satisfies you.
xargs rm < crop.lst  # fast-delete them in bulk 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM