Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: add 'sudo' to 'mv' if file isn't writable by $USER



On Wed, 14 Sep 2011, TJ Luoma wrote:

I'm wondering if someone has already done this.

I have a function which does this:


move () {
	command which -s gmv
	if [ "$?" = "0" ]
	then
		gmv --verbose --backup=numbered $@
	else
		mv -v -i $@
	fi
}

(simply put: use 'gmv' if it exists, otherwise use 'mv')

That works pretty well (although if there are ways to do it better, please let me know).

There's a pretty common zsh idiom to avoid the use of 'which' or 'where':

(( $+commands[command-name] ))

So:

move () {
    if (( $+commands[gmv] )) ; then
        gmv --verbose --backup=numbered $@
    else
        mv -v -i $@
    fi
}

HOWEVER, now I want to do

"If $FILE is writable by $USER, do 'move' as above. ELSE use 'sudo' before the mv or gmv command"

I can probably cobble together a solution, but I thought I'd check first to see if someone here had already invented this wheel.

For some things, I have it set up to:
1. try to do the thing
2. if it fails, try with sudo

E.g.:

mkdirp () { mkdir -p $argv || sudo mkdir -p $argv }

You get an extra warning when sudo's needed, but sometimes that's useful info. And the code's pretty simple. (Not sure why I prefer $argv over $@, exactly.) Maybe dangerous in the case of a move (if some, but not all, of the files are successfully moved without sudo).


For this particular problem, maybe something along the lines of:

move () {
    local -a cmd

    # check that destination is writable
    # or destination doesn't exist, but its dir is writable
    # otherwise, need sudo
    [[ -w $argv[-1] ]] || [[ ( ! -e $argv[-1] ) && -w ${argv[-1]}:h ]] || cmd+=( sudo )

    if (( $+commands[gmv] )) ; then
        cmd+=( gmv --verbose --backup=numbered )
    else
        cmd+=( mv -v -i )
    fi

    $cmd $argv
}

In a lot of cases, I would probably shorten:

if (( $+commands[blah] )) ; then
    # x
else
    # y
fi

when x and y both always return true¹, to:

(( $+commands[blah] )) && x || y

But that makes for a pretty long line here:

(( $+commands[gmv] )) && cmd+=( gmv --verbose --backup=numbered ) || cmd+=( mv -v -i )

--
Best,
Ben

¹: for most values of "always"


Messages sorted by: Reverse Date, Date, Thread, Author