0

I have file names in a file which I need to delete in a different directory.

Let's say I have x and y files in dir a. How do I delete it using cat?

I tried,

rm -f a/{`cat a.txt`}

a.txt has contents x,y,z.

If they are in the same folder, I can put x y z in a.txt and run,

rm -f `cat a.txt`

which works fine.

I have also tried,

rm -f "a/{"`cat a.txt`"}"

This command will go in a dockerfile so I prefer not to use any variables too.

I do not want to put a/x a/y a/z in the file which can be an option, as it is fixed that a will only contain the files. But a should be changed only in the dockerfile. Thanks for all suggestions in advance :)

1

Assuming your filenames don't contain spaces or any special characters, just reuse your original command with a cd before it:

(cd a; rm -f $(cat a.txt))

Be warned that rm -f `cat a.txt` breaks easily with spaces or any special characters in filenames, you should really use xargs with NUL-delimited filenames.

  • This would work. Though cd doesn't look like the best way to go. It still is better than all other options. Thanks :). – Optimus Prime Jun 29 '17 at 6:42
2

You should use while loop to read file line by line and then apply each line to rm. This a very common and frequently used approach in scripting

while IFS= read -r line
do
       rm a/"$line"
done < file.txt

Naturally the format of the file should be list of files with one file per line

  • Yes, this could work, but I would avoid while. Thanks :) – Optimus Prime Jun 29 '17 at 6:43
  • @OptimusPrime You're welcome. Mind if I ask why you want to avoid while loop ? – Sergiy Kolodyazhnyy Jun 29 '17 at 6:45
  • Just a preference :) A single line command looks much better and easier to understand. – Optimus Prime Jun 29 '17 at 6:56
1

Don't try to use $(cat file) for this kind of thing - it will break for example if there are spaces in file names e.g. given

$ cat a.txt 
foo
bar baz
bam

and

$ ls -Q a
"bam"  "bar baz"  "foo"  "other file"  "somefile"

then

$ (cd a ; rm $(cat ../a.txt))
rm: cannot remove 'bar': No such file or directory
rm: cannot remove 'baz': No such file or directory

Instead, you can use xargs

$ ls -Q a
"bam"  "bar baz"  "foo"  "other file"  "somefile"
$ xargs -a a.txt -I{} rm a/{}
$ ls -Q a
"other file"  "somefile"

If you really want to use cat, then combine it with xargs:

cat a.txt | xargs -I{} rm a/{}

(although given the -a feature, it's a Useless Use of Cat)


Note that -I{} implies -L 1 i.e. rm is invoked once for each line of the input file; if you don't need to prepend a directory path, then you can make the command more efficient by doing away with the -I in which case xargs will pass multiple arguments to rm. However in that case you should explicitly set the input delimiter to newline e.g. xargs -a a.txt -d '\n' rm to prevent breaking on spaces.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.