I was trying to write bash script that will run a command on certain fs events. So far I have succeeded in building fswatch and configuring it, but I cannot get bash to split a string into an array, to then switch case (if that exists) all the different events that I am watching for.
I always get some form of not a valid identifier and I dont even know what that is supposed to mean.
#!/usr/bin/bash
IFS=" "
fswatch -0 -xnr --event 2 --event 4 --event 8 --event 16 --event 128 --event 256 ./ \
| xargs -0 -n 1 -I {path} sh -c "echo {path}; read -a arr {path};"sh: line 0: read: `/run/media/twiggeh/Storage/projects/Clone/client/src/script.sh': not a valid identifier 5 1 Answer
The not a valid identifier message is telling you that you can't use a file path as a variable name (your code is expanding the read statement to something like read -a arr /path/to/my/directory. You're calling sh, which may not necessarily be a shell such as bash that even understands -a arr (dash, for example, would report dash: 1: read: Illegal option -a). Specify bash if you want bash.
However, I think you would do better to turn your code inside out (as it were). The following is bash code that will handle filenames containing not only whitespace but other strange characters (newline, etc.):
while IFS= read -d '' -r line
do # Split at the last space file="${line% *}" event="${line##* }" # Event and file are now separated printf "event=%s, file=%s.\n" "$event" "$file" # Put your case statements here # case "$event" ... esac
done < <(fswatch -0 -xnr --event 2 --event 4 --event 8 --event 16 --event 128 --event 256 ./)The redirect from fswatch... allows your main while loop to remain in the parent shell's context, so that any variables you set in the case...esac part remain accessible to the rest of the script. Using the more obvious fswatch ... | while ... do ... done construct would put the while loop into a subshell, preventing any variables it might set from being available in the remainder of the script.