jott19
jott19

Reputation: 421

How to escape path separators in file path?

I'm writing my first bash script and having trouble assigning a file path to a variable:

$target="/etc/httpd/conf/httpd.conf" 

It seems bash wants to interpret this with the "=" assignment operator resulting in the script throwing an error to the effect "No such file or directory."

Is there an easy way to do this? I've discovered I can assign a full path to a constant like this:

readonly TARGET=/etc/httpd/conf/httpd.conf

but that seems rather cumbersome. How would I perform string ops to modify/manipulate?

I've also discovered I can put full paths in an array like this:

declare -a cfile=('/root/.bashrc' '/etc/fstab')

All well and good, but how do I assign a file path to a variable?

== == == ==

finished! my first bash script - a basic config file manager

#!/bin/bash

# cfmgr.sh - configuration file manager bash script
# options: -get, -put
# '-get' creates SOURCEDIR/USERDIR and copies config files to USERDIR
# '-put' copies files in SOURCEDIR/USERDIR to system-defined locations on server
# purpose: helps with moving LAMP VMs to different hosts, bulk edits of
# of config files in editors like Notepad++, and backing up config files.

readonly SOURCEDIR=/usr/bin/_serverconfig
while [[ $# > 0 ]]
do
    arg="$1"
    shift
    case $arg in
        -put)
            put=true
            ;;
        -get)
            get=true
            ;;
        *)
            badarg=true
            ;;
    esac
done
clear
if [ $badarg ]; then
    echo "Invalid argument. Use either 'scf.sh -put' or 'scf.sh -get' to put"\
        "or get config files."
    exit
elif [ $get ]; then
    echo "Enter directory name to store files cfmgr will GET from this server:"
elif [ $put ]; then
    echo "Enter directory name containing files cfmgr will PUT to this server:"
else
    echo "Use either 'scf.sh -put' or 'scf.sh -get' to put or get config files."
    exit
fi
read -e -i $SOURCEDIR"/" USERDIR
pattern=" |'"
if [[ $USERDIR =~ $pattern ]]; then
    echo "Spaces not allowed.  Please try again."
    exit
fi
declare -a cfile=('/root/.bashrc' '/etc/fstab' '/etc/hosts' '/etc/networks'\
    '/etc/php.ini' '/etc/nsswitch.conf' '/etc/ntp.conf' '/etc/resolv.conf'\
    '/etc/sysctl.conf' '/etc/httpd/conf/httpd.conf' '/etc/selinux/config'\
    '/etc/samba/smb.conf' '/etc/samba/smbusers' '/etc/security/limits.conf'\
    '/etc/sysconfig/network' '/etc/sysconfig/network-scripts/ifcfg-eth0'\
    '/etc/sysconfig/network-scripts/ifcfg-eth1')
if [ $get ]; then
    if [[ -d "$USERDIR" ]]; then
        echo $USERDIR "directory already exists. Please try again."
        exit
    else
        mkdir -m 755 $USERDIR
    fi
    for file in ${cfile[@]}
    do
        if [ -e $file ]; then
            rsync -q $file $USERDIR
            if [ $? -eq 0 ]; then
                sleep 0.1
                printf "# "$file"\n"
            fi
        else
            printf "not found: "$file"\n"
        fi
    done
elif [ $put ]; then
    if [[ ! -d "$USERDIR" ]]; then
        echo $USERDIR "directory does not exist. Please try again."
        exit
    fi
    id=0    
    cd $USERDIR
    for item in *
    do
        if [[ -f $item ]]; then
            cdir[$id]=$item
            id=$(($id+1))
        fi
    done    
    for file in ${cdir[@]}
    do
        case $file in
        .bashrc)
            idx=0
            ;;
        fstab)
            idx=1
            ;;
        hosts)
            idx=2
            ;;
        networks)
            idx=3
            ;;
        php.ini)
            idx=4
            ;;
        nsswitch.conf)
            idx=5
            ;;          
        ntp.conf)
            idx=6
            ;;
        resolv.conf)
            idx=7
            ;;
        sysctl.conf)
            idx=8
            ;;
        httpd.conf)
            idx=9
            ;;
        config)
            idx=10
            ;;
        smb.conf)
            idx=11
            ;;
        smbusers)
            idx=12
            ;;
        limits.conf)
            idx=13
            ;;
        network)
            idx=14
            ;;      
        ifcfg-eth0)
            idx=15
            ;;
        ifcfg-eth1)
            idx=16
            ;;
        *)
            printf "not found: "$file"\n"
            continue
        esac
        target=${cfile[$idx]}
        if [[ -e $target ]]; then
            dtm=$(date +%Y-%m-%d)
            mv $target $target"."$dtm
        fi
        source=$USERDIR"/"$file
        dos2unix -q $source
        rsync -q $source $target
        if [ $? -eq 0 ]; then
            sleep 0.1
            printf "# "$target"\n"
        fi
    done
    read -p "reboot now? (y|n)" selection
    case $selection in
    [Yy]*)
        `reboot`
        ;;
    *)
        exit
        ;;
    esac
fi  
exit 0

Upvotes: 0

Views: 974

Answers (1)

John1024
John1024

Reputation: 113834

Instead of

$target="/etc/httpd/conf/httpd.conf" 

Use:

target="/etc/httpd/conf/httpd.conf" 

When bash sees the former, it first substitutes in for "$target". If target was empty, then the line that bash tries to execute, after the variable substitution and quote removal steps, is:

=/etc/httpd/conf/httpd.conf

Since there is no file named "=/etc/httpd/conf/httpd.conf", bash returns with a "No such file or directory" error.

Upvotes: 2

Related Questions