2

The following is part of a larger code I'm trying to figure out how to write the unrar statement within a for statement:

DST_DIR="/Volumes/Mac_Storage/Test_Folder"
cd "/Volumes/Mac_Storage/Test_Data"

find "$filePath" -type f "${EXT_OPTS[@]}" -exec sh -c '
for pathName do
    unzip -o '*.zip' && unrar e -r '*.rar' "$DST_DIR" && rm *.r* 
    echo "$pathName"
    printf "%s\n" "$pathName"
    sleep 1
done' sh {} +

The line in question:

unzip -o '*.zip' && unrar e -r '*.rar' "$DST_DIR" && rm *.r*

works perfectly fine out side but as soon as i add it to the for statement get a filename not matched error.

cheers

  • 1
    Where is DST_DIR set? or are you expecting it to take on the value(s) of pathName? – steeldriver Feb 12 at 2:56
  • The issue is almost certainly the $DST_DIR variable. Is this set anywhere earlier in your script? If not, maybe add it in. e.g. before your loop enter the line: DST_DIR=</your/desired/directory> – Crypteya Feb 12 at 2:59
  • DST_DIR is set further up my code, I've added to clear up where it comes from but outside the 'for' statement the command works. – madmiddle Feb 12 at 9:40
  • 1
    Add the line set -x to your script and it will output exactly what it's trying to do, including variable expansions. If you include the output from that in your question it'll be easier to answer. – Jenny D Feb 12 at 9:58
  • @JennyD I shall run that tonight and see what comes out the other end. – madmiddle Feb 12 at 10:43
1

The DST_DIR variable inside the sh -c script is distinct from the variable with the same name in shell that calls find. You would need to set DST_DIR inside the sh -c script, or pass it in when calling it.

find ... -exec sh -c '
    DST_DIR="/Volumes/Mac_Storage/Test_Folder"
    for pathName do
        # more code here
    done' sh {} +

Here, the variable gets its value as a literal string in the internal script. The DST_DIR variable could be deleted from the old location if you don't use it elsewhere.

Or,

find ... -exec sh -c '
    DST_DIR=$1; shift
    for pathName do
        # more code here
    done' sh "$DST_DIR" {} +

Here, the variable's value is passed from the outside environment into the internal script through the command line. The first argument, $1, holds the value when entering the script. This is assigned to the internal DST_DIR variable and then $1 is shifted off from $@. The loop then proceeds as before.

  • ah so it is treated as a separate shell script ? Can you pass more than one into it like you would passing from one .sh file to another. With this variable being passed in does the unzip command line now read correct ? – madmiddle Feb 12 at 10:15
  • @madmiddle Yes, the sh -c script is a totally separate script. You could actually have put it in its own file and called it with -exec ./myscript.sh {} + if you had wanted to (assuming then that DST_DIR is set inside the script). You should test on copies of real data ta convince yourself that it's working correctly. If you pass more command line arguments to it, be sure to shift these off before starting to loop over $@ (which holds the found pathnames). – Kusalananda Feb 12 at 10:22
  • ok. I see what you mean, the file path is passed to this script as parameter $1 so could I use -exec ./myscript.sh "$1" { } + ? and can you exit a for statement early ? – madmiddle Feb 12 at 11:04
  • @madmiddle No, the parameter would be in $1 inside the script. To call it from find and to pass $DST_DIR, you would use -exec ./myscript.sh "$DST_DIR" {} +. – Kusalananda Feb 12 at 11:24

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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