I know there are rules for quoting parameters, but no matter what I try, I can't seem to figure out how to make this work.
I have a function that takes a single filename as a parameter, then uses that filename to build a command line and runs the command line. I am able to make it work when there are no spaces in any of the files, but when a filename with a space is introduced, it breaks. Everything I try to make it work with spaces either doesn't work or causes it to not work on the files without spaces too.
Here is an example script that works with no spaces:
#!/bin/bash
list_files() {
file="${1}"
cmd="cat ${file}"
echo "Running command: '${cmd}'"
${cmd}
}
TARGET_DIR="${1}"
while IFS= read -d $'\0' -r file; do
list_files "${file}"
done < <(find ${TARET_DIR} -type f -print 0)
I just created a directory structure as follows:
./files/
|-- one # ==> Contains the text "files/one"
|-- two # ==> Contains the text "files/two"
|-- three and four # ==> Contains the text "files/three and four"
|-- five # ==> Contains the text "files/five"
When I run the above script on the directory above, I get the following output:
bash-3.2$ ./test.bash ./files
Running Command: 'cat ./files/one'
files/one
Running Command: 'cat ./files/two'
files/two
Running Command: 'cat ./files/three and four'
cat: ./files/three: No such file or directory
cat: and: No such file or directory
cat: four: No such file or directory
Running Command: 'cat ./files/five'
files/five
What am I doing wrong and how can I make a script like this work no matter what the file names are?
NOTE: For this example it would be simple enough to not store the command in a variable first and just print it then call it by typing the command itself twice, but for my real script, the command is much more complex and I would like to only have to maintain it in one place if it should need to change in the future.
cmd
in a variable, make it a function. There's no sane way to store a command in a variable. – Mikel Jun 03 '16 at 04:36