0

I'm trying to schedule my shell script but when it triggered to process on a scheduled task, there is this error prompt. but when no files are to be process it just displays the echo command.

here is my code:

if [ "$(ls -A $path)" ]
    then
    for file_name in "$path"/*; do
        filebasename=$(basename "$file_name")


        prefix=${filebasename:0:4};

        if [ "$prefix" == "abcd" ] ; then

            mv  "$file_name" "$out"

        fi                          

    done


    else echo "No files available at $path"
fi

and this is the error:

SH:prefix=${filebasename:0:4}:0403-011 The specified substitution is not valid for this command
5
  • The ${var:n:m} expansion is not available in /bin/sh. You'd need to specify ksh or bash for that. Same with the == operator. Commented Dec 4, 2017 at 1:07
  • hi glenn thanks for this, but what should i do ? do i need to reconstruct the syntax for the code? Commented Dec 4, 2017 at 1:19
  • 1
    You can add #!/bin/bash to the first line in your script Commented Dec 4, 2017 at 1:30
  • 2
    You also have some other syntax errors. Paste your code into shellcheck.net for further tips Commented Dec 4, 2017 at 2:08
  • thanks for this @glennjackman Commented Dec 4, 2017 at 5:37

2 Answers 2

1

You can write your code more simply this way:

#!/bin/bash

count=0
if [[ -d "$path" ]]; then
  for file_name in "$path"/abcd*; do
    [[ -f "$file_name" ]] && { ((count++)); mv "$file_name" "$out"; }
  done
fi

if ((count == 0)); then
  echo "No files available at $path"
fi

The advantages:

  • No need to parse the output of ls
  • No need to do basename + substring for each file
  • Skips any directories that have a name starting with abcd

In case you are not interested in knowing whether there were matching files or not, the whole thing can be written in a single line:

find "$path" -name "abcd*" -type f -exec mv "{}" "$out" \;
Sign up to request clarification or add additional context in comments.

7 Comments

It's worth mentioning that the last suggestion, using find, works in any shell and does not require bash. Oh, and the cd is redundant (unless $out is relative to $path).
Thanks @ghoti. I had to put in that cd because find wouldn't work without it on my Mac.
That sounds strange. find in macOS should work about the same way as everywhere else. What exactly was your command, and what error did you get? Was your $out in fact relative? Might want to read about -execdir. More about your answer.. You can avoid the [[ -f ... with a shopt -s nullglob (yes, even in bash 3). And you might want to include find's -maxdepth option too, to emulate the behaviour of a bash for loop without globstar.
The command depends on the values of the variables. You haven't mentioned the values of $path or $out that you tested with.
On macOS, a $path of just /tmp might not have worked since that's a symlink to /private/tmp. If you set path="/tmp/" (trailing slash) it should follow the symlink rather than evaluating it as a file. Alternately, you could use the -H or -L option for find.
|
0

i use this code: prefix=$(echo ${filebasename} | cut -c1-4)

instead of prefix=${filebasename:0:4};

now it completely running in my cronjob and no error as said earlier. thanks for the help guys ! :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.