As subtle as a flying brick.

Posts tagged “Folder (computing)

How to check if a directory exists in a shell script

To check if a directory exists and is a directory use the following syntax:

[ -d "/path/to/dir" ] && echo "Directory /path/to/dir exits." || echo "Error: Directory /path/to/dir does not exits."

The following version also check for symbolic link:

[ -d "/path/to/dir" && ! -L "/path/to/dir" ] && echo "Directory /path/to/dir exits." || echo "Error: Directory /path/to/dir exits but point to $(readlink -f /path/to/dir)."

OR

[ -d "/path/to/dir" && ! -h "/path/to/dir" ] && echo "Directory /path/to/dir exits." || echo "Error: Directory /path/to/dir exits but point to $(readlink -f /path/to/dir)."

Finally, you can use the traditional if..else..fi:

if [ -d "/path/to/dir" ]
then
    echo "Directory /path/to/dir exits."
else
    echo "Error: Directory /path/to/dir does not exits."
fi

Shell script examples to see if a ${directory} exists or not

 
#!/bin/bash
dir="$1"

[ $# -eq 0 ] && { echo "Usage: $0 dir-name"; exit 1; }

if [ -d "$dir" -a ! -h "$dir" ]
then
   echo "$dir found and setting up new Apache/Lighttpd/Nginx jail, please wait..."
   # __WWWJailSetup "cyberciti.biz" "setup"
else
   echo "Error: $dir not found or is symlink to $(readlink -f ${dir})."
fi

In this example, create directories if does not exits:

# Purpose: Setup jail and copy files
# Category : Core
# Override : No
# Parameter(s) : d => domain name
#                action => setup or update
__WWWJailSetup(){
        local d="$1"
        local action="${2:setup}"       # setup or update???
        local index="$d

$d

" # default index.html
        local J="$(_getJailRoot $d)/$d" # our sweet home 
        local _i=""

        [ "$action" == "setup" ] && echo "* Init jail config at $J..." || echo "* Updating jail init config at $J..."
        __init_domain_config "$d"

        [ "$action" == "setup" ] && echo "* Setting up jail at $J..." || echo "* Updating jail at $J..."
        [ ! -d "$J" ] &&  $_mkdir -p "$J"

        for _i in $J/{etc,tmp,usr,var,home,dev,bin,lib64}
        do
                [ ! -d "$_i" ] &&  $_mkdir -p "$_i"
        done
        for _i in $_lighttpd_webalizer_base/$d/stats/{dump,out}
        do
                [ ! -d "$_i" ] &&  $_mkdir -p "$_i"
        done
        for _i in $_lighttpd_webalizer_prepost_base/$d/{pre.d,post.d}
        do
                [ ! -d "$_i" ] &&  $_mkdir -p "$_i"
        done
## truncated 
}

Summary

Use the following to check file/directory types and compare values:

  1. -L "FILE" : FILE exists and is a symbolic link (same as -h)
  2. -h "FILE" : FILE exists and is a symbolic link (same as -L)
  3. -d "FILE" : FILE exists and is a directory
  4. -w "FILE" : FILE exists and write permission is granted

 


Get only the latest version of a file from across mutiple directories

bash$ find . -name custlist\* | perl -ne '$path = $_; s?.*/??; $name = $_; $map{$name} = $path; ++$c; END { print $map{(sort(keys(%map)))[$c-1]} }'

Explanation

The purpose of this is to find the the “latest” version of the custlist_*.xls file from among multiple versions in directories and sub-directories, for example:

./c/custlist_v1.003.xls
./c/custlist_v2.001.xls
./d/b/custlist_v1.001.xls
./d/custlist_v1.002.xls

Let’s decompose the one-liner to the big steps:

  • find . -name custlist\* — find the files matching the target pattern
  • ... | perl -ne '...' — run perl, with the input wrapped around in a while loop so that each line in the input is set in the variable $_
  • $path = $_; s?.*/??; $name = $_; — save the full path in $path, and cut off the subdirectory part to get to the base name of the file and save it in $name
  • $map{$name} = $path; — build a mapping of $name to $path
  • ++$c; — we count the elements, to use it later
  • (sort(keys(%map)))[$c-1] — sort the keys of the map, and get the last element, which is custlist_v2.001.xls in this example
  • END { print $map{$last} }' — at the end of all input data, print the path of the latest version of the file

Limitations

Even if the latest version of the file appears multiple times in the directories, the one-liner will print only one of the paths. This could be fixed though if needed.