$ touch {comic5,{a..d}}.zip './--e=BEGIN{unlink for <c*>}#.zip'
$ ls
a.zip b.zip comic5.zip c.zip d.zip '--e=BEGIN{unlink for <c*>}#.zip'
$ rename 's/\.zip$/\.cbz/' *.zip
$ ls
a.zip b.zip d.zip '--e=BEGIN{unlink for <c*>}#.zip'
Oops! All the files whose name starts with c
have been removed.
For the File::Rename
implementation of rename
, this kind of issue was fixed in 1.99 (on my request) but Ubuntu 22.04 comes with version 1.30.
Here, you'd want instead:
rename 's/\.zip\z/\.cbz/' ./*.zip
With that ./
prefix preventing any of the zip file names from being taken as an option by rename
¹.
Or, with that particular implementation of rename
, pass the file list via its standard input instead of arguments:
printf '%s\0' *.zip | rename -0 's/\.zip/\.cbz/'
Which with shells where printf
is builtin (most) also works around the Argument list too long
limit.
Or use zsh
's zmv
instead which doesn't have this kind of problem, has some extra safeguards and is generally easier to use²:
autoload -Uz zmv
zmv '(*).zip' '$1.cbz'
Now, this kind of thing is unlikely to happen by chance. If that's what happened, someone would have planted a malicious similarly named file in the current directory with the knowledge that you would run such a command.
If the malicious code did unlink()
or if the files were removed as the result of a rename()
replacing the file, you might have some luck using some filesystem undelete/recovery approach. If it did the equivalent of what shred
/wipe
do or encrypted the contents before moving the files elsewhere as ransomware would do, your best option would be restoring from backup.
In the absence of malicious file names, rename
should not normally lose data as it checks whether the target file exists before renaming. You might lose symlink files though if the target of those symlinks are not accessible as rename
uses -e <the-target>
and that would return false for a symlink that doesn't resolve like for the -e
of the [
utility:
$ touch a.zip
$ ln -s /x a.bcz
$ ls -n
total 4
lrwxrwxrwx 1 1000 1000 2 Dec 22 08:39 a.bcz -> /x
-rw-r--r-- 1 1000 1000 0 Dec 22 08:39 a.zip
$ rename -v 's/\.zip$/\.bcz/' *.zip
a.zip renamed as a.bcz
$ ls -n
total 0
-rw-r--r-- 1 1000 1000 0 Dec 22 08:39 a.bcz
Oops! That (broken) a.bcz
symlink is gone.
But symlinks take very little space on disk, so that couldn't explain the 80 out of 120GiB loss that you suffered from.
Like Chris, I suspect your problem was elsewhere. Your files may even still be there, only not in the directory you think they should be. Try a sudo find / -iname 'comic5.zip' -o -iname 'comic5.cbz'
¹ Also note the \z
in place of $
which you generally want to use in regexps that match things other than lines as $
matches either at the end of the subject (which you want here) or before a newline character at the end of the subject (which you don't want though in this particular case, the subject ends in .zip
and not newline, so that wouldn't be a problem).
² even if generally slower as it calls one mv
per file. Though you can run zmodload zsh/files
to get a builtin mv
.
I tested it and you are right that rename will not replace files with the same name, but either way, the files are definitely not there.
– image_muck Dec 21 '23 at 21:16