12

As title says, is there any difference for *NIX filesystems? e.g ls file and ls ./file

Sergey Alaev
  • 263
  • 1
  • 8
  • 1
    You might ask http://unix.stackexchange.com/ -- the answers so far all have good information in them, but neither really feels like _the_ answer. – Rob Starling Oct 21 '16 at 23:53

2 Answers2

14

I'm not crazy about the explanation by SmallLoanOf1M. It is technically correct but answers in a way that doesn't match the usage example in the question.

So by way of example, here is one important difference between the two from the question: "file" and "./file"

What if the file is named with a character that is parsed by the shell? Especially regarding characters interpreted by the command one is running.

Specifically, the "dash" character: "-". But other characters are meaningful to the shell.

Example. My file was named "-dingle"

Try to list the file:

ls -dingle
# ls -dingle
ls: invalid option -- 'e'

Even worse, what if the file was named "-rf rmbomb *"? Now try removing it

rm "-rf rmbomb *"

I'm not even gonna try to run that example, but hopefully you get the idea.

So how do you list a file staring with dash? Use ./ in front.

# ls ./-dingle
./-dingle

Ditto for rm

JDS
  • 2,598
  • 4
  • 30
  • 49
  • That is a valid way to process some files with odd names, and my answer didn't consider files like that. One could also use a literal instead in all of the examples above, in the form of a backslash preceding odd characters, including the spaces specified above. An example of that would be so: `ls \-dingle` or `ls \-rf\ rmbomb\ \*`. This can be a good way to ensure that any given set of commands are at least consistent, as specifying `./` before a name won't escape characters after the `./`. – Spooler Oct 21 '16 at 21:35
  • 2
    It happens that, since escapes are escaped by the shell, not the command, and params are parsed by the command, escaping or quoting the - does nothing useful. – Dewi Morgan Oct 21 '16 at 22:08
  • INDEED! In the special case of a dash *after a command* it does appear to do absolutely nothing. I wonder if a `./` is the only way to get rid of that. It might be. – Spooler Oct 21 '16 at 22:11
  • It appears that a double-dash delimiter `--` is a also a valid way of doing this, in addition to `./`. such as `ls -- -dash` or `rm -- -dash`. – Spooler Oct 21 '16 at 22:26
  • The "-" is not special to the shell, it's only special to commands that treat it as a special character (i.e. for options). You can't delete a file named "-i" by typing `rm -i`, but you can delete it by typing `unlink -i` (`unlink` doesn't have options). Chars that are special to the shell are handled by quoting them or escaping them. `rm -i` behaves just like `rm '-i'` since the shell doesn't care about the '-', but if you want to delete a file named `$file`, you can delete it with `rm '$file'` or `rm \$file` because the "$" is special character to the shell so quoting or escaping it works. – Johnny Oct 22 '16 at 02:06
  • 2
    You make it sound like `rm "-rf rmbomb *"` would actually do something bad, instead of just making `rm` print an error. It's only dangerous if you forget to quote the filename, so word-splitting happens. (esp. in a shell script where you run `rm $file` instead of `rm "$file"`. But in that case, the `*` won't expand, because glob expansion doesn't happen on the contents of variable expansion. If you want that, you'd need an `eval`.) Anyway, if your script word-splits filenames before passing to rm, I'd make a file called `space -rf .` or something, so `rm ./$i` doesn't help. – Peter Cordes Oct 22 '16 at 03:20
  • 1
    BTW, the actual error message is `rm: invalid option -- ' '`, from when it tries to interpret the space after `-rf` as a single-character switch, because it's part of the same argument. (And yes, I ran this inside an empty directory just in case I had overlooked something and it was actually dangerous :P) – Peter Cordes Oct 22 '16 at 03:21
  • 2
    @PeterCordes: wordsplitting and globbing DOES occur on the results of unquoted variable expansion and command substitution, unless suppressed by `IFS=''` and `-f` respectively. A rarer example is that `awk` treats an operand (other than a first operand that is the script) having form `foo=bar` as an assignment to execute but `./foo=bar` as a file to read. – dave_thompson_085 Oct 22 '16 at 06:26
  • @dave_thompson_085: oh yes, thanks for catching that mistake. `foo=\*; echo $foo` does expand the glob. I had the order backwards; I know that word-splitting happens on `rm ./$i` (and tried to say that). Anyway, definitely goes into the "avoid this in the first place with proper quoting" category, which is easier than remembering all the corner cases of what can go wrong if you don't! – Peter Cordes Oct 22 '16 at 06:33
  • Another alternative, at least on GNU, is to use the double hyphen to terminate options processing. `ls ./-dingle` and `ls -- -dingle` have the same effect of listing the file named `-dingle` in the current directory if one exists, and complaining if it does not. This is a common pattern for many GNU programs that accept file names on the command line, and many other applications also implement it (probably by falling back to the default behavior of GNU getopt). – user Oct 22 '16 at 10:50
7

Yes.

By issuing file on the command line, BASH will search your $PATH environment variable for a file of that name. Unless the file resides in a directory within your $PATH variable, it won't be found.

. means the current directory. ./ means within the current directory, in relative terms. It is the equivalent of saying something like /home/sheogorath/shivering/isles.img when invoking ./isles.img while working in the /home/sheogorath/shivering/ directory.

As such, it's commonly used to execute files within your working directory "in place".

EDIT: In your example, ls is being called upon by the shell and found by using the path variable. Its argument will be processed in your working directory, whatever that may be. Since this is the default for ls, you won't see any difference between specifying file and explicitly specifying ./file as they both point to your current directory.

Not all commands will accept file paths in the working directory, and some expect to have you state files in a directory that they themselves pre-define via configuration. Among commands that accept files as arguments, these commands are less common

Spooler
  • 7,046
  • 18
  • 29
  • 1
    That is bash, but I was wondering about path resolution in general – Sergey Alaev Oct 21 '16 at 20:04
  • 1
    This is the way any shell I've ever heard of works. BASH is merely the most commonly used. – Spooler Oct 21 '16 at 20:04
  • 4
    $PATH is only relevant for commands and has nothing to with file name arguments that follow a command such as `ls` mentioned in the original question. That is more the difference between refferencing a *relative path* ( relative to the current working directory) I.e. `../../dir/filename` and an *absolute path* `/path/to/dir/filename` – HBruijn Oct 21 '16 at 20:21
  • @HBruijn both paths in my question are relative. Question is whether they *always* point to the same file – Sergey Alaev Oct 21 '16 at 20:31
  • 1
    +1 for Sheogorath... and a correct answer. – Corey Ogburn Oct 21 '16 at 20:37
  • 1
    If they're arguments to a command that attempts to find files in the working directory by default, they will be the same. Thus, for `ls` they will always be the same path, one specified more explicitly than the other. Not all commands behave this way when processing arguments, but most do. – Spooler Oct 21 '16 at 20:38
  • Found this: http://man7.org/linux/man-pages/man7/path_resolution.7.html It is a bit more complicated because of links, mount points, permissions, roots... but answer seems to be that they are the same. – Sergey Alaev Oct 21 '16 at 20:42
  • -1 for incorrect answer for 2 reasons: (1) Bash is not involved, not is any other shell. The pathname in question here is an argument to `ls`, which the shell (Bash or otherwise) passes as is; (2) re: "Since this is the default for `ls`": it's not any kind of default for `ls`, it's just how pathname resolution works. – Celada Oct 22 '16 at 11:12
  • I think you meant Bash, not BASH – cat Oct 22 '16 at 11:20