Be cautious: The command you seek to run could cause loss of data!
If you don't think your file names contain newlines or double quotes, then you could use:
find . -type f -name '?*.*' |
sed 's/\(.*\)\.[^.]*$/mv "&" "\1"/' |
sh
This generates your list of files (making sure that the names contain at least one character plus a .
), runs each file name through the sed
script to convert it into an mv
command by effectively removing the material from the last .
onwards, and then running the stream of commands through a shell.
Clearly, you test this first by omitting the | sh
part. Consider running it with | sh -x
to get a trace of what the shell's doing. Consider making sure you capture the output of the shell, standard output and standard error, into a log file so you've got a record of the damage that occurred.
Do make sure you've got a backup of the original set of files before you start playing with this. It need only be a tar
file stored in a different part of the directory hierarchy, and you can remove it as soon as you're happy with the results.
You can choose any shell; this doesn't rely on any shell constructs except pipes and single quotes and double quotes (pretty much common to all shells), and the sed
script is version neutral too.
Note that if you have files xyz.c
and xyz.h
before you run this, you'll only have a file xyz
afterwards (and what it contains depends on the order in which the files are processed, which needn't be alphabetic order).
If you think your file names might contain double quotes (but not single quotes), you can play with the changing the quotes in the sed
script. If you might have to deal with both, you need a more complex sed
script. If you need to deal with newlines in file names, then it is time to (a) tell your user(s) to stop being silly and (b) fix the names so they don't contain newlines. Then you can use the script above. If that isn't feasible, you have to work a lot harder to get the job done accurately — you probably need to make sure you've got a find
that supports -print0
, a sed
that supports -z
and an xargs
that supports -0
(installing the most recent GNU versions if you don't already have the right support in place).