开发者

Exclude string from wildcard in bash

开发者 https://www.devze.com 2022-12-28 03:15 出处:网络
I\'m trying to adapt a bash script from \"Sams\' Teach Yourself Linux in 24 Hours\" which is a safe delete command called rmv. The files are removed by calling rmv -d file1 file2 etc. In the original

I'm trying to adapt a bash script from "Sams' Teach Yourself Linux in 24 Hours" which is a safe delete command called rmv. The files are removed by calling rmv -d file1 file2 etc. In the original script a max of 4 files can by removed using the variables $1 $2 $3 $4. I want to extend this to an unlimited number of files by using a wildcard. So I do:

for i in $*
do
mv $i $HOME/.trash
done

The files are deleted okay but the option -d of the command rmv -d is also treated as an argument and bash objects that it cannot be found. Is there a better way to do this?

Thanks, Peter

#!/bin/bash
# rmv - a safe delete program
# uses a trash directory under your home directory
mkdir $HOME/.trash 2>/dev/null
# four internal script variables are defined
cmdlnopts=false
delete=false
empty=false
list=false
# uses getopts command to look at command line for any options
while getopts "dehl" cmdlno开发者_运维问答pts; do
  case "$cmdlnopts" in
    d ) /bin/echo "deleting: \c" $2 $3 $4 $5 ; delete=true ;;
    e ) /bin/echo "emptying the trash..." ; empty=true ;;
    h ) /bin/echo "safe file delete v1.0"
        /bin/echo "rmv -d[elete] -e[mpty] -h[elp] -l[ist] file1-4" ;;
    l ) /bin/echo "your .trash directory contains:" ; list=true ;;
  esac
done

if [ $delete = true ]
then
  for i in $* 
  do
  mv $i $HOME/.trash
  done
  /bin/echo "rmv finished."
fi
if [ $empty = true ]
then
  /bin/echo "empty the trash? \c"
  read answer
  case "$answer" in
    y) rm -i $HOME/.trash/* ;;
    n) /bin/echo "trashcan delete aborted." ;;
  esac
fi
if [ $list = true ]
then
  ls -l $HOME/.trash
fi


You can make use of shift here.

Once you find -d is one of the options in the switch, you can shift and get rid of -d from the positional parameters. Next you can

until [ -z $1 ] ; do
 mv $1 $HOME/.trash
 shift
done


getopts sets OPTIND to the index of the first argument after the options. (#)

So after parsing the options you can do:

shift $OPTIND-1

to remove the options from the argument list.

Then use "$@" rather than $*, and you can handle files with spaces in them.


Thanks a lot!

I changed the code to read:

#!/bin/bash
# rmv - a safe delete program
# todo: add ability to handle wildcards
# uses a trash directory under your home directory
mkdir $HOME/.trash 2>/dev/null
# four internal script variables are defined
cmdlnopts=false
delete=false
empty=false
list=false
# uses getopts command to look at command line for any options
while getopts "dehl" cmdlnopts; do
  case "$cmdlnopts" in
    d ) echo -e "deleting: \n" "${@:2}" ; delete=true ;;
    e ) echo -e "emptying the trash..." ; empty=true ;;
    h ) echo -e "safe file delete v1.0"
        echo -e "rmv -d[elete] -e[mpty] -h[elp] -l[ist] file [...]" ;;
    l ) echo -e "your .trash directory contains:" ; list=true ;;
  esac
done
shift $OPTIND-1

if [ $delete = true ]
then
  for i in $@
  do
  mv $i $HOME/.trash
  done
  echo "rmv finished."
fi
then
  /bin/echo "empty the trash? \c"
  read answer
  case "$answer" in
    y) rm -i $HOME/.trash/* ;;
    n) /bin/echo "trashcan delete aborted." ;;
  esac
fi
if [ $list = true ]
then
  ls -l $HOME/.trash
fi

This deletes the files as desired but I get this error:

/home/peter/rmv: line 21: shift: 2-1: numeric argument required
mv: invalid option -- 'd'
Try `mv --help' for more information.


You need to use

shift $(($OPTIND - 1))

to get red of the processed command line args. Try this version:

#!/bin/bash
# rmv - a safe delete program
# uses a trash directory under your home directory
mkdir -p $HOME/.trash 

# uses getopts command to look at command line for any options
while getopts "dehl" cmdlnopts; do
    case "$cmdlnopts" in
    d ) delete=true;;
    e ) echo "emptying the trash..." ; empty=true ;;
    h ) echo "safe file delete v1.0"
            echo "rmv -d[elete] -e[mpty] -h[elp] -l[ist] files" ;;
    l ) echo "your .trash directory contains:" ; list=true ;;
    esac
done

shift $(($OPTIND - 1))

if [ -n "${delete}" ]; then
    echo "deleting: " "${@}"
    mv ${@} $HOME/.trash
    echo "rmv finished."
fi

if [ -n "${empty}" ]; then
    read -p "empty the trash? " answer
    case "$answer" in
    y) rm -i $HOME/.trash/* ;;
    n) echo "trashcan delete aborted." ;;
    esac
fi

if [ -n "${list}" ]; then
    ls -l $HOME/.trash
fi


Late to the party, but for Googlers, this will generate the error Peter describes:

shift $OPTIND-1

while the syntax in Jurgen's reply will not:

shift $(($OPTIND-1))

The problem is that $OPTIND-1 is interpreted as a string, and shift can't use a string as an argument. $(( )) is Bash's arithmetic expansion operator. You put a string inside it, the string is evaluated as an arithmetic expression, and the value returned.

0

精彩评论

暂无评论...
验证码 换一张
取 消