path.sh
Go to the documentation of this file.
00001 ############################################################################## 00002 # @file os/path.sh 00003 # @brief Path manipulation functions. 00004 # 00005 # Copyright (c) 2011, 2012 University of Pennsylvania. All rights reserved.<br /> 00006 # See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file. 00007 # 00008 # Contact: SBIA Group <sbia-software at uphs.upenn.edu> 00009 ############################################################################## 00010 00011 [ "${_BASIS_OS_PATH_INCLUDED}" == 'true' ] || { 00012 _BASIS_OS_PATH_INCLUDED='true' 00013 00014 00015 . "`cd -P -- \`dirname -- "${BASH_SOURCE}"\` && pwd`/../config.sh" || exit 1 00016 00017 00018 ## @addtogroup BasisBashUtilities 00019 # @{ 00020 00021 00022 # ---------------------------------------------------------------------------- 00023 ## @brief Clean path, i.e., remove occurences of "./", duplicate slashes,... 00024 # 00025 # This function removes single periods (.) enclosed by slashes or backslashes, 00026 # duplicate slashes (/) or backslashes (\), and further tries to reduce the 00027 # number of parent directory references. 00028 # 00029 # For example, "../bla//.//.\bla\\\\\bla/../.." is convert to "../bla". 00030 # 00031 # @param [in] path Path. 00032 # 00033 # @return Cleaned path. 00034 normpath() 00035 { 00036 local _basis_cp_path="$1" 00037 # GNU bash, version 3.00.15(1)-release (x86_64-redhat-linux-gnu) 00038 # turns the array into a single string value if local is used 00039 if [ ${BASH_VERSION_MAJOR} -gt 3 ] || [ ${BASH_VERSION_MAJOR} -eq 3 -a ${BASH_VERSION_MINOR} -gt 0 ]; then 00040 local _basis_cp_dirs=() 00041 else 00042 _basis_cp_dirs=() 00043 fi 00044 # split path into parts, discarding redundant slashes 00045 while [ -n "${_basis_cp_path}" ]; do 00046 if [ ${#_basis_cp_dirs[@]} -eq 0 ]; then 00047 _basis_cp_dirs=("`basename -- "${_basis_cp_path}"`") 00048 else 00049 _basis_cp_dirs=("`basename -- "${_basis_cp_path}"`" "${_basis_cp_dirs[@]}") 00050 fi 00051 _basis_cp_path="`dirname -- "${_basis_cp_path}"`" 00052 if [ "${_basis_cp_path}" == '/' ]; then 00053 _basis_cp_path='' 00054 fi 00055 done 00056 # build up path again from the beginning, 00057 # discarding dots ('.') and stepping one level up for each '..' 00058 local _basis_cp_i=0 00059 while [ ${_basis_cp_i} -lt ${#_basis_cp_dirs[@]} ]; do 00060 if [ "${_basis_cp_dirs[${_basis_cp_i}]}" != '.' ]; then 00061 if [ "${_basis_cp_dirs[${_basis_cp_i}]}" == '..' ]; then 00062 _basis_cp_path=`dirname -- "${_basis_cp_path}"` 00063 else 00064 _basis_cp_path="${_basis_cp_path}/${_basis_cp_dirs[${_basis_cp_i}]}" 00065 fi 00066 fi 00067 let _basis_cp_i++ 00068 done 00069 # return 00070 echo -n "${_basis_cp_path}" 00071 } 00072 00073 # ---------------------------------------------------------------------------- 00074 ## @brief Get absolute path given a relative path. 00075 # 00076 # This function converts a relative path to an absolute path. If the given 00077 # path is already absolute, this path is passed through unchanged. 00078 # 00079 # @param [in] path Absolute or relative path. 00080 # 00081 # @return Absolute path. 00082 abspath() 00083 { 00084 local _basis_tap_base="$1" 00085 local _basis_tap_path="$2" 00086 if [ "${_basis_tap_base:0:1}" != '/' ]; then 00087 _basis_tap_base="`pwd`/${_basis_tap_base}" 00088 fi 00089 if [ "${_basis_tap_path:0:1}" != '/' ]; then 00090 _basis_tap_path="${_basis_tap_base}/${_basis_tap_path}" 00091 fi 00092 normpath "${_basis_tap_path}" 00093 } 00094 00095 # ---------------------------------------------------------------------------- 00096 ## @brief Get canonical file path. 00097 # 00098 # This function resolves symbolic links and returns a cleaned path. 00099 # 00100 # @param [in] path Path. 00101 # 00102 # @return Canonical file path without duplicate slashes, ".", "..", 00103 # and symbolic links. 00104 realpath() 00105 { 00106 # make path absolute and resolve '..' references 00107 local _basis_grp_path=`abspath "$1"` 00108 if ! [ -e "${_basis_grp_path}" ]; then echo -n "${_basis_grp_path}"; return; fi 00109 # resolve symbolic links within path 00110 _basis_grp_path=`cd -P -- $(dirname -- "${_basis_grp_path}") && pwd -P`/`basename -- "${_basis_grp_path}"` 00111 # if path itself is a symbolic link, follow it 00112 local _basis_grp_i=0 00113 local _basis_grp_cur="${_basis_grp_path}" 00114 while [ -h "${_basis_grp_cur}" ] && [ ${_basis_grp_i} -lt 100 ]; do 00115 _basis_grp_dir=`dirname -- "${_basis_grp_cur}"` 00116 _basis_grp_cur=`readlink -- "${_basis_grp_cur}"` 00117 _basis_grp_cur=`cd "${_basis_grp_dir}" && cd $(dirname -- "${_basis_grp_cur}") && pwd`/`basename -- "${_basis_grp_cur}"` 00118 let _basis_grp_i++ 00119 done 00120 # If symbolic link could entirely be resolved in less than 100 iterations, 00121 # return the obtained canonical file path. Otherwise, return the original 00122 # link which could not be resolved due to some probable cycle. 00123 if [ ${_basis_grp_i} -lt 100 ]; then _basis_grp_path="${_basis_grp_cur}"; fi 00124 # return 00125 echo -n "${_basis_grp_path}" 00126 } 00127 00128 00129 ## @} 00130 # end of Doxygen group 00131 00132 00133 } # _BASIS_PATH_INCLUDED