mv /home/user/oldname /home/user/newname
Answer from Rafał Cieślak on askubuntu.commv /home/user/oldname /home/user/newname
mv can do two jobs.
- It can move files or directories
- It can rename files or directories
To just rename a file or directory type this in Terminal:
mv old_name new_name
with space between the old and new names.
To move a file or directory type this in Terminal.
mv file_name ~/Desktop
it will move the file to the desktop.
Videos
Assuming all subdirectories in /path/to/directory follow that naming convention:
cd /path/to/directory
prename -n 's~/\d{4}[a-z]? - ~/~i' */*
prename is the Perl rename (any of the variants will do).
This prints:
mv ...Which is exactly the command I want to execute. But I can't execute it.
I tried assigning the output to a variable and executing it by calling the variable. That didn't work. I tried a few variations on that idea, and I got errors.
It feels like I'm missing some tool here.
The easy way you are looking for is to append | bash to your command. That's how you can go from "a command which prints a command" to "actually running the command that was printed."
However, even though you've included double quotes in the command to be printed, this is a bad idea to include in a script.
- Why does my shell script choke on whitespace or other special characters?
You may have handled the whitespace aspect, but what if the filenames include double quote characters directly? Or newlines? Or variable names (which will be expanded within double quotes)?
The only characters that are illegal in filenames are a slash (/) and a null byte.
In writing scripts you should hold yourself to a much higher standard of robustness than you might at an interactive command line.
At a command line, you can see the command you are about to run, you can confirm it's correct, and you can then run it. In a script, there is no oversight and no confirmation. The script will do what you told it to do, no matter how destructive that may turn out to be.
So the correct approach is actually to use find, as detailed in my other answer. This will handle any filenames correctly and doesn't contain arbitrary code execution vulnerabilities.
This is an entirely trivial one-liner; for example:
rename_pieces smali/com/FOLDER/SUB-FOLDER smali/com/NEW/SUBNEW
...assuming, of course, that you run an appropriate function definition first. If you only want to rename SUB-FOLDER, after creating NEW-NAME should it not exist, that would look like:
rename_pieces() {
local old=
2
[[ $new = */* ]] && mkdir -p -- "${new%/*}"
mv -T -- "$old" "$new"
}
...and this is much more likely to be the behavior you really do want than any other interpretation, insofar as it leaves contents of FOLDER other than SUB-FOLDER alone with its original name.
By contrast, if you really want to rename both directories, that gets a lot more interesting. If we have a guarantee that both source and destination are at the same depth, this might look something like:
log_or_run() {
if [[ $log_only ]]; then # just log what we would run
printf '%q ' "$@" >&2 # use printf %q to generate a safely-escaped version
printf '\n' >&2 # ...and terminate with a newline.
else
"$@" # actually run the command
fi
}
rename_pieces() {
local old=
2 common
while [[ ${old%%/*} = "${new%%/*}" ]]; do
common+=/"${old%%/*}"
old=${old#*/}; new=${new#*/}
done
while [[ $old && $new ]]; do
log_or_run mv -T -- "${common#/}/${old%%/*}" "${common#/}/${new%%/*}"; echo
common+=/"${new%%/*}"
[[ $old = */* && $new = */* ]] || return
old=${old#*/}; new=${new#*/}
done
}
Whereafter:
log_only=1 rename_pieces smali/com/FOLDER/SUB-FOLDER smali/com/NEW/SUBNEW
...emits on output:
mv -T -- smali/com/FOLDER smali/com/NEW
mv -T -- smali/com/NEW/SUB-FOLDER smali/com/NEW/SUBNEW
...and doing likewise without log_only=1 actually runs those commands.
Can't think of anything more elegant, but the following should work:
find . -path '.*com/FOLDER/SUBFOLDER' | awk '{new_dir=$1; sub("/FOLDER/SUBFOLDER","/NEW/SUBNEW", $new_dir); printf("mkdir -p %s\nmv %s %s\n", $new_dir, $1, $new_dir);}' > cmds
That gets all the required mv commands in the cmds file. Verify it is correct, and then execute using sh cmds. Although this isn't the most fun, I like this approach when dealing with important data because it is always better to verify what you're going to run.
Edit: Fixed the issue pointed out in comments about the script not creating the directory if it does not exist.