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
1
  • 3
    I'm pretty sure the reason it works with two slashes is for exactly this purpose.
    – jesse_b
    Jan 7, 2018 at 4:11

3 Answers 3

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.

2
  • @Freedo, yea but that will only work with a single argument.
    – jesse_b
    Jan 8, 2018 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, 2018 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 '/'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .