==================== Unix/Linux Pathnames ==================== -IAN! idallen@freenet.carleton.ca A Unix pathname consists of components separated by slashes, e.g. /home/idallen/bin/argv.sh If there are no slashes in the pathname, the pathname is looked for as a name in the current directory. To be a valid pathname, every component to the left of the rightmost slash in a pathname must either be a directory or be a symbolic link to a directory. The final component in the pathname can be anything - a file, directory, symbolic link, or other special file. In the above example, there are four directories - four components to the left of the rightmost slash. The names of those four directory components are "" (the ROOT directory, which has no name), "home", "idallen", and "bin". The final component happens to be a file name "argv.sh". --------------- Dot and Dot Dot --------------- Every Unix directory contains the name ".", which is a name that leads right back to the directory in which it is found. Every directory contains the name "..", which is a name that leads to the unique parent directory of the directory in which it is found. The ROOT directory is the only directory that is its own parent. ("." and ".." are the same in the ROOT directory.) The pathname /tmp contains two directories: ROOT and "tmp". The pathname /tmp/. contains three directories, ROOT, "tmp", and ".". The "." is searched for in the "tmp" directory, and leads right back to "tmp"; so, /tmp and /tmp/. are usually equivalent. The pathname /./tmp contains three directories: ROOT, ".", and "tmp". The "." is searched for in the ROOT directory, and leads right back to ROOT; so, /./tmp and /tmp are equivalent. The pathname /./tmp/. contains four directories: ROOT, ".", "tmp", and ".". The first "." is searched for in the ROOT directory; the second "." is searched for in the "tmp" directory. Thus, /./tmp/. is usually equivalent to /tmp. The pathname /tmp/.. contains three directories: ROOT, "tmp", and "..". The ".." is searched for in the "tmp" directory, and leads to the parent of the "tmp" directory (which is ROOT in this case); so, /tmp/.. and / are usually equivalent. The pathname /home/idallen/bin/../.. contains six directories: ROOT, "home", "idallen", "bin", "..", and "..". The first ".." is searched for in the "bin" directory and leads to the parent of the "bin" directory, which is "idallen". The second ".." is therefore searched for in the "idallen" directory, and leads to the parent of the "idallen" directory, which is "home". Thus, /home/idallen/bin/../.. is usually equivalent to /home. The pathname /../tmp contains three directories: ROOT, "..", and "tmp". The ".." is searched for in the ROOT directory, and leads to the parent of the ROOT directory, which is also ROOT. ROOT is the only directory that is its own parent. Thus, /../tmp is the same as /tmp. Similarly, /../../../../../tmp is also the same as /tmp. If any of the pathname components are symbolic links to directories, not real directories, then the actions of "." and ".." are not so well behaved and the answers may differ from those given above. The ROOT directory can never be a symbolic link; so, /. and /.. (and /./. and /../../.., etc.) are always the same as / all by itself. ------------------------------- Relative vs. Absolute pathnames ------------------------------- A pathname is absolute if, after the shell has finished with it, the pathname starts with a slash. (If it starts with a slash, the nameless ROOT directory is the first directory in the pathname.) Otherwise, the pathname is relative to the current working directory. --------- Exercises --------- Given this current working directory: $ pwd /tmp/idallen and this sub-structure in the current directory: $ ls -l drwxr-xr-x 2 idallen idallen 4096 Feb 3 20:33 dir1 -rw-r--r-- 1 idallen idallen 0 Feb 3 20:33 file1 All the relative pathnames below give the same output, because all these relative pathnames refer to the same (current) directory: $ ls $ ls . $ ls ./. $ ls ././././././. $ ls dir1/.. $ ls ./dir1/.. $ ls dir1/../. $ ls dir1/../././././. $ ls ../idallen $ ls ./../idallen/./././. $ ls ../../tmp/idallen $ ls ../idallen/dir1/.. $ ls ../idallen/dir1/.././././. $ ls dir1/../../idallen $ ls ./dir1/../../idallen/. All the absolute pathnames below also give the same output, because all these absolute pathnames refer to the same (/tmp/idallen) directory: $ ls /tmp/idallen $ ls /tmp/idallen/././. $ ls /tmp/idallen/dir1/.. $ ls /tmp/../tmp/idallen/../idallen/dir1/.. $ ls /././tmp/./././../tmp/./././idallen/./././../././idallen/./dir1/./.. All the relative pathnames below give the same output, because all these relative pathnames refer to the same sub-directory "dir1": $ ls dir1 $ ls dir1/. $ ls ./dir1 $ ls ./dir1/. $ ls ././././dir1/././././. $ ls ../idallen/dir1 $ ls ../idallen/dir1/../dir1/. $ ls ../../tmp/idallen/dir1/../../idallen/dir1/. All the absolute pathnames below give the same output, because all these absolute pathnames refer to the same sub-directory "/tmp/idallen/dir1": $ ls /tmp/idallen/dir1 $ ls /tmp/../tmp/idallen/dir1 $ ls /tmp/../tmp/idallen/../idallen/dir1 $ ls /tmp/../tmp/idallen/../idallen/dir1/../dir1 $ ls /././tmp/./././idallen/./././dir1/./. All the relative pathnames below give the same output, because all these relative pathnames refer to the root directory (from /tmp/idallen): $ ls ../.. $ ls ../../../../.. $ ls dir1/../../.. $ ls dir1/../dir1/../../.. $ ls ../idallen/../.. $ ls ../../tmp/.. $ ls ../../tmp/idallen/../.. $ ls ../../tmp/idallen/../../tmp/idallen/../../././././. All the absolute pathnames below give the same output, because all these absolute pathnames refer to the root directory: $ ls / $ ls /. $ ls /./././. $ ls /tmp/.. $ ls /tmp/idallen/../.. $ ls /tmp/../tmp/idallen/../.. $ ls /tmp/idallen/dir1/../../.. These shell patterns match all non-hidden names in the /tmp/idallen directory: $ echo * $ echo ./* $ echo dir1/../* $ echo ../idallen/* $ echo ../../tmp/idallen/* $ echo /tmp/idallen/* $ echo /tmp/idallen/dir1/../* These patterns match all non-hidden names in the /tmp directory: $ echo ../* $ echo ./../* $ echo .././* $ echo /tmp/* $ echo /tmp/./* $ echo /././././tmp/./././* These patterns match all non-hidden names in the root directory: $ echo ../../* $ echo ../../../../../../* $ echo /* $ echo /tmp/../* $ echo /tmp/idallen/../../* $ echo /tmp/idallen/dir1/../../../* All these commands copy the "file1" into "file2" in the same (current) directory of "/tmp/idallen": $ cp file1 file2 $ cp ./file1 ./file2 $ cp ././././././file1 ././././././file2 $ cp file1 ../idallen/file2 $ cp ../idallen/file1 file2 $ cp ../idallen/file1 ../idallen/file2 $ cp ../../tmp/idallen/file1 file2 $ cp file1 ../../tmp/idallen/file2 $ cp ../../tmp/idallen/file1 ../../tmp/idallen/file2 $ cp ./././././../../tmp/idallen/file1 ./././././../../tmp/idallen/file2 This is a valid pathname: $ ls dir1/. This is not a valid pathname: $ ls file1/. Question: What does "echo */." output? This is a valid pathname: $ ls ./dir1 This is also a valid pathname: $ ls ./file1 Question: What does "echo ./*" output? What is the difference between "./*" and "*/." ?