13

I hid some files using the command:

mv * .*

but now I am unable to find them. I tried using:

mv .* *

but nothing happened (an error was shown). If I run:

ls -la

it's showing:

total 8  
drwxrwxr-x 2 abhishek abhishek 4096 Mar  9 20:46 .  
drwxrwxr-x 4 abhishek abhishek 4096 Mar  9 20:46 ..  

Is there any way to recover my hidden files?

BeastOfCaerbannog
  • 12,964
  • 10
  • 49
  • 77
  • The key thing here is that the glob stars `*` are processed before `mv` ever gets the chance to look at the command line. You can use `$ echo mv .* *` to preview the command line before running it, so you can see what `mv` sees. – jpaugh Mar 11 '21 at 18:52

1 Answers1

44

Your files are not hidden, you have moved all files (and directories if any) one directory up.

This happens because mv * .* won't work as you think it will. The command mv will only move one file to one file (rename) or move one or multiple files to a directory. It won't move multiple files to multiple files with some smart renaming.


What happened?

Let's assume we have one directory and 3 files in our directory:

dir1
file1
file2
file3

Some Shells (e.g. bash, dash, ...) will expand your command to:

mv dir1 file1 file2 file3 . ..

Your expanded command fits the second form of the SYNOPSIS you find at man mv:

mv [OPTION]... SOURCE... DIRECTORY

Note the . and ..:

  • . is the current directory,
  • .. is one directory up.

The command means: move dir1, file1, file2 and file3 and . to ..; It will also essentially give an error, something like:

mv: cannot move '.' to '../.'

But given you have write permission in that directory, all other files have been moved. You can find your files in .. (= one directory up). However, files with same name have been overwritten and you won't know which files was in which directory before.


If you had a subdirectory .hidden-dir, it would have expanded to:

mv dir1 file1 file2 file3 . .. .hidden-dir

Then, all files would have been moved to .hidden-dir. However, this seems not the case for you, because the you would have seen .hidden-dir in your ls -la output.


How to fix

Run:

mv ../dir1 ../file1 ../file2 ../file3 .

However, you need to know the names.


What you should have used

mmv '*' '.#1'

or

rename 's/^/./' *
pLumo
  • 26,204
  • 2
  • 57
  • 87
  • 4
    *and you won't know which files was in which directory before.* - all the files that were moved will have the same `ctime` - `ls -a -lcrt` is useful to sort files by ctime with the most recent ones at the bottom. – Peter Cordes Mar 10 '21 at 15:25
  • 8
    It *might* have moved one directory up. It will move to whatever directory shows up last in the expansion of `.*`, which might some hidden directory, especially if this was done in a user's home directory or a directory under version control. I would recommend running `ls -1d | tail -n1` in that directory. (in this case, he had an otherwise empty directory ... but others might not be so fortunate) – Joe Mar 10 '21 at 15:47
  • True, I added that information to the question. However, it is not the case here as OP issued `ls -la` without output. – pLumo Mar 10 '21 at 16:24
  • 2
    Shell also matters. For example, zsh doesn't match files `..` nor `.` for any glob. – JoL Mar 10 '21 at 23:34
  • Thanks, also added that it only happens for some shells – pLumo Mar 11 '21 at 06:50
  • 1
    Note that `mmv` and `rename` may not be available everywhere. It would also probably be a good thing to emphasise the fact it`s `mmv` and not `mv` for the hurried reader . – jcaron Mar 11 '21 at 13:11
  • `for x in *; do mv -i "$x" ".$x"; done`. – spectras Mar 12 '21 at 11:59
  • @spectras this will work if people have neither `mmv` or `rename`. However, at least `rename` is installed by default in Ubuntu and will be a lot faster for many files, as your loop will invoke `mv` for each file separately. – pLumo Mar 12 '21 at 15:20
  • We are talking microseconds on a command you would run a few times a month at most, I really doubt that is relevant… – spectras Mar 12 '21 at 20:20