GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)
Ubuntu 20.04.3 LTS
So, I downloaded like 20 7z files and I wanted to move them somewhere, but NOT the previous 7z files I already had in Downloads. (The filenames had some spaces in them, too, btw.) So I did like
mv `find -mmin -700 -iname "*.7z" -printf "\"%f\" "` ~/FOLDER/
which should have found all 7z files modified in the last ~11 hrs or so, and moved them to ~/FOLDER/.
Instead of moving all the files, it gives me a heap of errors with fragments of the filenames, like
mv: cannot stat 'Pinball': No such file or directory
I've tried the find
command on its own, and it gives me a reasonable-looking list of files, each surrounded by quotes, all on one line. I ALSO tried pasting the output of the find
command into mv PASTED_HERE ~/FOLDER/
, like I thought the backticks basically DID, and it worked fine. (I also tried $()
instead of the backticks, but I got the same errors as with the backticks.) What's going wrong?
mv $(find …) …
(or equivalent with backticks) is basically as flawed asfor f in $(find …); do …
, the Bash pitfall number 1. – Kamil Maciorowski Jan 03 '22 at 18:55Don't_stop_me_now.mp3
in the variablef
, then running something likels $f
doesn't go on to process the single quote as a quote character. If it did, it would be impossible to work with arbitrary filenames in the general case, as a filename could also contain double quotes and spaces... – ilkkachu Jan 03 '22 at 19:44echo *.txt
into the console, I get*.txt
, but if I typels $(echo *.txt)
into the console, I get a list of filenames. (Based on the rest of the discussion here, I wouldn't expect it to behave properly with e.g. filenames-with-spaces, but it does seem to be expanded, at least.) Is this consistent with what you were saying? – Erhannis Jan 03 '22 at 19:49rm $(cat files.txt)
, then yes, the shell would expand the command substitution by running the command inside, removing any trailing newlines, word splitting and globbing the result and passing the resulting fields as arguments torm
. But it wouldn't process any quotes on the output. It also wouldn't process any quotes on the result of the*.txt
glob. – ilkkachu Jan 03 '22 at 19:52ls $(echo *.txt)
wouldn't work if the glob gave any filenames with whitespace (or something like*.txt
which itself is a valid filename...). And that's exactly because the result of$(echo ...)
is word-split, while the plain glob*.txt
as such isn't. – ilkkachu Jan 03 '22 at 19:54"hello $(bad command) && echo foo"
, and it would work fine withrm ./*
, or indeed if the name was contained in a variable, and you didrm "$filename"
. Zsh doesn't do word splitting on variables by default, (err, but I think it does on command substitutions, for some reason) and it has better tools on controlling it too, and for using the output of e.g.find -print0
. – ilkkachu Jan 03 '22 at 19:58