4

I have this code :

for file in "$@"*png; do
  echo "$file"
done

It works only if you provide a path that ends with / like /root/.

What would be the correct way to add / to the path input, in situations like this, without breaking my script?

If you give a path input without / at the end, it just does this :

File: /root*png

If I modify it to be for file in "$@"/*png; do and input /root/test/ it works but the result looks ugly :

File: /root/test//sample2.png
  • 3
    I'm pretty sure the reason it works with two slashes is for exactly this purpose. – Jesse_b Jan 7 '18 at 4:11
7

ilkkachu pointed out a major flaw in my answer and corrected it in his so please give him the credit he deserves. I've come up with another solution though:

#!/bin/bash

for dir in "$@"; do
        find "$dir" -type f -name '*png' -exec readlink -f {}  \;
done

Example:

$ ll
total 6
-rwxr-xr-x 1 root root 104 Jan  7 14:03 script.sh*
drwxr-xr-x 2 root root   3 Jan  7 04:21 test1/
drwxr-xr-x 2 root root   3 Jan  7 04:21 test2/
drwxr-xr-x 2 root root   3 Jan  7 04:21 test3/

$ for n in {1..3}; do ll "test$n"; done
total 1
-rw-r--r-- 1 root root 0 Jan  7 04:21 testfile.png
total 1
-rw-r--r-- 1 root root 0 Jan  7 04:21 testfile.png
total 1
-rw-r--r-- 1 root root 0 Jan  7 04:21 testfile.png

$ ./script.sh test1 test2/ test3
/root/temp/test1/testfile.png
/root/temp/test2/testfile.png
/root/temp/test3/testfile.png

Original Solution:

for file in "${@%/}/"*png; do
  echo "$file"
done

The ${@%/} will trim any / off the end of your parameter and then the / outside will add it back -- or add it to any parameter that didn't have one.

  • @Freedo, yea but that will only work with a single argument. – Jesse_b Jan 8 '18 at 1:20
  • Thanks for adding the original answer back, if you wish to add you can also replace @, by $1 or $2... and it will work just fine with multiple arguments. – Freedo Jan 15 '18 at 7:13
3

Using $@ with the glob like that seems somewhat odd. If you expect it to be able to process multiple arguments, well, it won't work. The strings surrounding $@ are only attached to the first and list item.

$ mkdir a b; touch a/a.png b/b.png
$ set -- a b 
$ echo x"$@"x
xa bx
$ echo "$@/"*.png
a b/b.png

So, to handle multiple arguments, you'll need to loop over "$@" separately:

for arg in "$@"; do
    for file in "${arg%/}"/*.png; do
         echo "$file"
    done 
done

In another case, you could you could use the string substitution expansion ${//} (in Bash or zsh) to add a suffix to each positional parameter, but it's rather difficult to get that to work with a glob.

0

You can use tr too.

Always add / at the end and ...

file='/root/test//sample2.png';echo "$file" | tr -s '/'

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.