2

I have a shell script that needs to delete the file names from the /tmp directory. The file names must be detected from a list of file names passed to my script.

./deletetmpfiles.sh /var/moht/test1.pdf  /var/shif/log/test4.pdf 

Any number of files can be passed as arguments to the deletetmpfiles.sh script.

Considering the above example.

My script should delete /tmp/test1.pdf & /tmp/test4.pdf

Below is what I attempted.

echo "Deleting the following files as they got printed: $@"

cd /home/system/bey.de/invoices/send4print

if [ $? -eq 0 ]; then
  echo "Deleting the following on the server: $@"
  echo "rm -f /tmp/$(basename $@)"
  rm -f /tmp/$(basename $@)
fi

But it deletes only the first file from /tmp i.e /tmp/test1.pdf and misses deleting the remaining files.

Can you please suggest?

1
  • 1
    basename doesn't deal with multiple files. Commented Feb 6, 2021 at 14:54

2 Answers 2

3

basename doesn't deal with multiple files:

NAME

basename - strip directory and suffix from filenames   

SYNOPSIS

  basename NAME [SUFFIX]    basename OPTION...NAME...

Unless the -a option is used (GNU Coreutils):

-a, --multiple
   support multiple arguments and treat each as a NAME

But it would break if the filenames have newlines.

And will fail in your command, since basename -a will return the arguments with new lines

basename "$@"
foo.pdf
bar.pdf

Which breaks the rm command since the arguments passes are separated by new lines.

This code apparently solves the problem

rm $(echo "$(basename -a "$@")")

but I'm not so sure of its validity.


Yo can then loop over the arguments:

for i in "$@"; do 
  echo "rm -f /tmp/$(basename "$i")"
  rm -f "/tmp/$(basename "$i")"
done

To deal with names with spaces, they must be properly escaped when passed to the script:

$ script.sh "foo bar.pdf"

Or

$ script.sh foo\ bar.pdf
5
  • 1
    oops. :) But yeah, correctly quoted, it should be fine with whitespace. Commented Feb 6, 2021 at 15:04
  • GNU coreutils basename supports multiple arguments with -a (and -z for NUL-terminated output), but that doesn't make the rm easier... Commented Feb 6, 2021 at 15:19
  • 1
    basename -a could be coerced to use, but it would break if the filenames have newlines. And -z would be pretty much impossible to use in a script. It might have been better if they'd not even implemented things like that. Commented Feb 6, 2021 at 15:42
  • @ilkkachu If you want you can check my updated answer. Commented Feb 6, 2021 at 16:12
  • 1
    @schrodigerscatcuriosity, well, in that rm-echo-basename command, the step with echo adds the word splitting that adding quotes around "$(basename -a "$@")" inhibits. So you could just do rm $(basename -a "$@") instead. But that breaks on regular spaces too (so you need to change IFS), and uses the names as globs (so you need to disable that), which is pretty much why I didn't want to go there in the first place. :) It's better to do it with a loop (which we already have here!), that way the filenames are separate from the go, and stay separate for the whole time. Commented Feb 6, 2021 at 17:14
-1

I would suggest getting a solid basic knowledge before proceeding to more complicated stuff.

As usually there are more ways to accomplish given task.

A fundamental question of your example is: "What exactly $@ stands for?"

Answer might be: "all the command line arguments as separate, individual strings." (Robbins & Beebe: Classic Shell Scripting)

If you want to process all the individual members of this argument, you would need a cycle.

Variant 1:

for file in "$@" ; do
  echo "Deleting the following on the server: $file"
  file=$(basename $file)
  echo "rm -f /tmp/$file"
  rm -f /tmp/$file
done

Variant 2:

until [ $# = 0 ]; do
  echo "Deleting the following on the server: $file"
  file=$(basename $file)
  echo "rm -f /tmp/$file"
  rm -f /tmp/$file
  shift
done

In variant 2 shift makes the argument list shorter every iteration.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.