Unix: delete files listed in a file

I have a long text file with a list of file masks that I want to delete

Example:

/tmp/aaa.jpg /var/www1/* /var/www/qwerty.php 

I need delete them. Tried rm `cat 1.txt` and it says the list is too long.

I found this command, but when I check the folders from the list, some of them still have xargs rm <1.txt files xargs rm <1.txt Manual rm deletes files from such folders, so there are no permissions problems.

+70
linux unix
Feb 28 2018-11-21T00:
source share
12 answers

This is not very efficient, but will work if you need glob templates (as in / var / www / *)

 for f in $(cat 1.txt) ; do rm "$f" done 

If you do not have templates and you are sure that your paths in the file do not contain spaces or other strange things, you can use xargs as follows:

 xargs rm < 1.txt 
+90
Feb 28 2018-11-28T00:
source share

Assuming the file list is in the 1.txt file, follow these steps:

 xargs rm -r <1.txt 

The -r option calls recursion to any directories named in 1.txt .

If any files are read-only, use the -f option to force delete:

 xargs rm -rf <1.txt 



Be careful about entering any tool that performs program deletions. Make sure that the files specified in the input file really need to be deleted. Be especially careful with seemingly simple typos. For example, if you enter a space between a file and its suffix, it will be two separate file names:

 file .txt 

there are actually two separate files: file and .txt .

This may not seem so dangerous, but if a typo looks something like this:

 myoldfiles * 

Then, instead of deleting all files starting with myoldfiles , you delete myoldfiles and all non-fuel files and directories in the current directory. Probably not what you wanted.

+47
Jan 23 '14 at 7:26
source share

Use this:

 while IFS= read -r file ; do rm -- "$file" ; done < delete.list 

If you need the glob extension, you can omit the quote from $file :

 IFS="" while read -r file ; do rm -- $file ; done < delete.list 

But keep in mind that file names may contain β€œproblematic” content, and I would use a version without quotes. Imagine this template in a file

 * */* */*/* 

This will remove a lot from the current directory! I would advise you to prepare a deletion list so that globe patterns are no longer required, and then use quotation marks, as in my first example.

+14
Feb 18 '14 at 9:14
source share

You can use '\ n' to define a newline character as a separator.

 xargs -d '\n' rm < 1.txt 

Be careful with -rf because it can remove what you don't need if 1.txt contains paths with spaces. This is why the new line separator is a bit safer.

On BSD systems, you can use the -0 option to use newlines as a delimiter:

 xargs -0 rm < 1.txt 
+14
Jun 01 '16 at 12:08 on
source share

xargs -I{} sh -c 'rm {}' < 1.txt should do what you want. Be careful with this command, because an incorrect entry in this file can cause many problems.

This answer was edited after @tdavies indicated that the original does not extend the shell.

+13
Feb 28 2018-11-21T00:
source share

You can use this single line liner:

 cat 1.txt | xargs echo rm | sh 

Which makes shell expansion, but does rm minimum number of times.

+12
Feb 28 2018-11-28T00:
source share

cat 1.txt | xargs rm -f | bash cat 1.txt | xargs rm -f | bash Run command will only do for files.

cat 1.txt | xargs rm -rf | bash cat 1.txt | xargs rm -rf | bash Run command will execute the following recursive behavior.

+4
Dec 21 '17 at 10:41
source share

In this particular case, due to the dangers indicated in the other answers, I would

  • Change for example. Vim and :%s/\s/\\\0/g , escaping all whitespace with a backslash.

  • Then :%s/^/rm -rf / , adding the command. With -r you don’t have to worry about directories being listed after the files contained in it, and with -f it won’t complain because there are no files or duplicate entries.

  • Run all the commands: $ source 1.txt

+3
Dec 22 '14 at 11:49
source share

Here is another loop example. It also contains an "if-statement" as an example of checking if the entry is a "file" (for example, a "directory"):

 for f in $(cat 1.txt); do if [ -f $f ]; then rm $f; fi; done 
+1
Jun 10 '15 at 21:43
source share

Here you can use a set of folders from deleteelist.txt , and avoid some templates as well

 foreach f (cat deletelist.txt) rm -rf ls | egrep -v "needthisfile|*.cpp|*.h" end 
0
Jan 23 '14 at 6:54
source share

This will allow file names to have spaces (reproducible example).

 # Select files of interest, here, only text files for ex. find -type f -exec file {} \; > findresult.txt grep ": ASCII text$" findresult.txt > textfiles.txt # leave only the path to the file removing suffix and prefix sed -i -e 's/:.*$//' textfiles.txt sed -i -e 's/\.\///' textfiles.txt #write a script that deletes the files in textfiles.txt IFS_backup=$IFS IFS=$(echo "\n\b") for f in $(cat textfiles.txt); do rm "$f"; done IFS=$IFS_backup # save script as "some.sh" and run: sh some.sh 
0
Dec 02 '17 at 14:41
source share

Just to provide a different way, you can also just use the following command

 $ cat to_remove /tmp/file1 /tmp/file2 /tmp/file3 $ rm $( cat to_remove ) 
0
Jun 07 '19 at 13:21
source share



All Articles