'Well it's only passing mv a list of--' yeah yeah yeah, I know, and that's why I'm calling bullshit. It should be massively harder to execute filenames. Even if 1970s decisions make that the eternal hideous default: the lack of any idiot-proof standard workaround is incomprehensible.
StackOverflow's full of competing one-liners and people pointing out how each one is considered harmful. The least-skeezy options use exec. That sentence should make anyone recoil in horror.
This is not a filename problem. This is a tool problem. If a single printable character is going to silently expand into a list of names, then for god's sake, having it put each name in quotes should be fucking trivial.
This is not standard behavior. Got links to StackOverflow?
This works just fine in bash and zsh:
encoded_funky_name=IUAjJCVeJiooKVtde30nIjo7IGxzOyAmYW1wOyA8Plx8YH5gJChscykke1BBVEh9ISF8fCYmLmpwZw==
# decodes to: !@#$%^&*()[]{}'":; ls; & <>\|`~`$(ls)${PATH}!!||&&.jpg
mkdir temp
cd temp
mkdir temp2
touch "$(echo "${encoded_funky_name}" | base64 -d)"
mv ./*.jpg temp2
ls -lR
mv temp2/*.jpg .
ls -lR
Note that it is recommended to use "./" before a raw * in globs to avoid filenames beginning with "-" being interpreted by the command as special arguments (this is not necessary in the above example, but it is a good habit). See https://dwheeler.com/essays/filenames-in-shell.html#globbing for more info. e.g.:
touch ./-laR
# Bad ls command:
ls *
# Good ls command:
ls ./*
having it put each name in quotes should be fucking trivial
This is effectively what happens, except that it's actually more robust than that, since it also accounts for names with quotes and other special characters. Glob expansion does NOT output file names into the shell; it passes them as arguments to the command with no further shell processing. Arguments can contain any special characters.
Not sure why you're seeing this behavior. Are you doing something with these file names before passing them to mv? Storing them in variables? Saving them to files?
mv ./*.jpg /mnt/Example/Pictures works fine, though, so thank you for the practical solution. I'm still disgusted there's any filename that gets treated as... not a filename. That broken stair might be older than I am.
Ahhh. That's a confusing thread, with a couple confounding factors.
The OP in that thread is attempting to a batch rename, which is out of scope of the mv command.
If you are NOT trying to change the name of the file, I recommend always making the last argument of mv your destination directory, rather than the destination file. This is strictly mandatory if you are moving multiple files.
OP in that SO thread used the filename as the destination path — a filename which did not exist, and therefore could not be resolved by the wildcard. And if it had existed, the move would have failed. Because of that, mv /data/*/Sample_*/logs/*_Data_time.err /data/*/Sample_*/logs/*_Data_time_orig.err is not a valid command.
OP cannot accomplish what they want with a single mv command. They would need to use a loop or something like find.
I agree that the lack of universal consistency in how commands handle arguments is unfortunate. There's no way around that without reinventing the entire OS. Many commands let you pass -- as an argument to signify that any subsequent arguments should not be interpreted as options even if they begin with -. But that's entirely up to the implementation of each program; it's not a shell feature.
Future OS designers: consider typed arguments. Abandon all legacy cruft.
Note that it is recommended to use “./” before a raw * in globs to avoid filenames beginning with “-” being interpreted by the command as special arguments
Jackpot! I think! Based on OP's reply to me, this is almost definitely the real problem:
mv *.jpg /mnt/Example/Pictures
Where it will then die with an error like mv: invalid option -- '1' depending on the contents of the current directory.
Is this some recent news that you expect us to have heard of? Your post demands context that is not easily understood (but it's possible to understand through multiple reads)
What shell are you using?
I'm using bash (GNU bash, version 5.1.16(1)-release) and don't observe this behavior:
$ ls
'first file.txt' 'second file.txt'
$ cat 'first file.txt'
this is originally named "first file.txt"
$ cat 'second file.txt'
this is originally named "second file.txt"
$ mv *.txt
$ ls
'second file.txt'
$ cat 'second file.txt'
this is originally named "first file.txt"
It's possible that whatever shell you're using has a bug, but it's definitely not universal. It's also possible that this bug only affects builtins like mv and not non-builtin commands.
When I run into situations like this, I use the commands that work to write out a script. Eg, in your case the wildcard isn't working with the mv command, so do something like this:
Can you run printf %s\\n *.jpg in that same directory and share the result? I'm really intrigued. If there's private information in there, I'd be satisfied with just a handful of lines showing the issue with private info replaced with ****s
Edit: also run alias mv to check whether you have an alias messing things up
I'm also a bit lost. From the final sentence "having it put each name in quotes should be fucking trivial." OP seems to complain that filenames with spaces expand into multiple arguments. I can't recreate this with this command in bash:
$ printf %s\\n *.jpg
This command prints each argument in its own line. Replace *.jpg with whatever to prove it to yourself. Filenames with spaces show in full in a single line for me.
Which you'd think would mean mv "thing.jpg" "other thing.jpg", but no, it does mv thing.jpg other thing.jpg - and then chokes, because other is not a valid option or filename. Possibly after writing the contents of other thing.jpg onto the destination thing.jpg.
If any filenames contain characters like ; or &, you better hope the next word doesn't look like a command.