20

I'm learning unix commands from a UNIX Tutorial for Beginners at surrey.ac.uk where I found a weird way to move a file. In particular, I have the folder unixstuff in the home directory, inside the unixstuff there is the folder backups and the files Caiti.txt and Caiti.bak.

According to the above link, to move the Caiti.bak file from unixstuff to backups I have to make sure that the current directory is unixstuff and I have to run the command:

mv Caiti.bak backups/.

Could you explain the meaning of the /. characters, please? The dot means current directory (unixstuff in this case). If I run the command:

mv Caiti.bak backups

it works anyway.

5
  • 6
    “The dot means current directory (unixstuff in this case).” Not quite, it means the directory at whatever point in the path it is — the current directory when it’s on its own, the backups directory when it comes after that as in backups/.. It’s an actual directory in each directory, pointing to the directory containing it. Aug 26, 2020 at 8:04
  • Hello @StephenKitt thank you very muc for your explanation. Now it's more clear. Aug 26, 2020 at 8:15
  • 4
    Modern versions of mv (and some similar commands) have an additional option like mv -t target file .... This has two benefits. (a) It explicitly checks target is a directory, avoiding the rename-file ambiguity. (b) It is suitable for use with xargs because the file list comes last, not the target directory name. Aug 26, 2020 at 10:26
  • Adding to what @StephenKitt said, on older filesystems, . is actually a directory entry on disk. The special handling of . in POSIX compliant systems was inherent to the filesystem structure itself originally, not the VFS. However, many newer filesystems do not store physical . (and ..) entries in the directory, instead generating them for readdir() calls as-needed, though that's still part of the FS itself and not the VFS layer in most cases (though the VFS is usually responsible for normalization of stuff like ./././.). Aug 27, 2020 at 1:52
  • The second example will "work" if the directory backups doesn't exist yet, but it won't do what you were expecting, and would be disastrous in the long run.
    – Shadur
    Aug 28, 2020 at 7:22

1 Answer 1

46

TL;DR

This forces the destination to be a directory that already exists or the command to fail without effect and is used as a fail-safe.


The meaning of .

Every directory in typical Unix/Unix-like filesystems include two special directories: one referencing the directory where it is: . and one referencing the parent directory of where it is: .. (allowing to move back in the hierarchy of directories). They are relative to where they are found. So the directory . inside a directory named backups references backups. To tell it otherwise, when there's a directory named backups, backups/. is equivalent to backups.


Different behaviors with the source or destination being a file or directory

  • If the directory exists, the two commands will have the same effect: when the target is a directory mv will move source(s) to that directory. That's the expected outcome.

  • If the target backups is a file instead of the directory:

    • 1st case will fail with the error Not a directory
    • 2nd case will rename Caiti.bak and overwrite backups
  • If the target doesn't exist:

    • 1st case will fail with No such file or directory
    • second command will rename the file Caiti.bak into the file backups, leading to the previous case and possible loss of data the next time it happens.

That's good practice to append /. to a directory target supposed to be existing and abort a script at an error from this.

All these cases would work the same when only appending / if the source is a file rather than a directory.

If we can't assume this, this example where the source is a directory:

mv somedirectory targetnothere/

would not fail (and somedirectory will be renamed instead of being put into targetnothere or abort). The extra . will make this case fail too:

$ mv somedirectory targetnothere/.
mv: cannot move 'somedirectory' to 'targetnothere/.': No such file or directory
1
  • 5
    To remove the need for these sublte hacks (and path manipulations if paths are supplied from elsewhere), mv had a -t switch that has the same effect regardless of how the target is written. Aug 27, 2020 at 3:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .