You are not logged in.

#1 2006-10-07 13:30:52

sweiss
Member
Registered: 2004-02-16
Posts: 635

Irm - Inverse rm

This is a script I wrote, which clears the current working folder, apart from the files listed as parameters.

e.g.:

[sweiss@raviv2 gambas]$ ls
filelist  gambas-1.0.14-1.pkg.tar.gz  gambas-1.0.14.tar.bz2  pkg  PKGBUILD  src
[sweiss@raviv2 gambas]$ irm PKGBUILD gambas-1.0.14-1.pkg.tar.gz
[sweiss@raviv2 gambas]$ ls
gambas-1.0.14-1.pkg.tar.gz  PKGBUILD

I thought I'd share it with you.
Important: This script is written in BASH, and I am not at all an expert. It also does not yet handle files/directories inside subdirectories - If you try doing `irm ./src/file`, the script will quit with an error message and do nothing.
Also, it may be inefficient - If it is, please let me know how to correct it. I suggest reviewing the code in the script before running it - it's not much.

Anyway, here it is:

#!/bin/sh

LS=$(which ls)
WC=$(which wc)
FIND=$(which find)
GREP=$(which grep)
RM=$(which rm)
SED=$(which sed)
AWK=$(which awk)
FILENAME=
GREP_COMMAND=

# Removes any leading 
prep_filename()
{
  if ! [ -n "$1" ]
  then
    return
  fi
  
  FILENAME="$1"
  
  if [ $(echo "$FILENAME" | cut -c1-2) = "./" ]
  then
    FILENAME=$(echo "$FILENAME" | cut -c3-)
    prep_filename "$FILENAME"
  fi
  
  if [ $(echo "$FILENAME" | rev | cut -c1) = "/" ]
  then
    FILENAME=$(echo "$FILENAME" | rev | cut -c2- | rev)
    prep_filename "$FILENAME"
  fi
}

IS_FIRST_FILE=1
for i in $(seq 1 $#)
do
  filename=${!i}
  if ! [ -e "$filename" ]
  then
    echo "No such file or directory: ${filename}"
    exit 1
  fi
  
  prep_filename "$filename"
  
  if [ $(echo "$FILENAME" | sed 's:/::g') != "$FILENAME" ]
  then
    echo irm does not yet support keeping directories/files inside subdirectories. Aborted.
    exit 1
  fi
  
  if [ $IS_FIRST_FILE -eq 1 ]
  then
    GREP_COMMAND=${GREP_COMMAND}"$GREP -vx "$FILENAME""
    IS_FIRST_FILE=0
  else
    GREP_COMMAND=${GREP_COMMAND}" | $GREP -vx "$FILENAME""
  fi
done

# The icky sed part is for escaping the  characters, if such exist.
FILES_TO_REMOVE=$(echo $(eval "$LS -1 -A . | ${GREP_COMMAND} | $SED 's:"'\'":"'\\'":g' | $AWK '{print "\""$0"\""}'"))

if ! [ -n "$FILES_TO_REMOVE" ]
then
  echo No files removed.
  exit 1
fi

eval "$RM -rf $FILES_TO_REMOVE"

Enjoy.

Offline

#2 2006-10-07 13:54:24

lucke
Member
From: Poland
Registered: 2004-11-30
Posts: 4,018

Re: Irm - Inverse rm

Incidentally, zsh has something like that built in.

You just use "rm ^foobar" (or "rm ^(foo1|foo2)") and it erases everything except that. And it's not limited to rm.

Offline

#3 2006-10-07 23:24:14

codemac
Member
From: Cliche Tech Place
Registered: 2005-05-13
Posts: 794
Website

Re: Irm - Inverse rm

o/ zsh.

remember you have to had extended globbing turned on for that to work if I remember.

Offline

#4 2006-10-09 07:23:57

shadowhand
Member
From: MN, USA
Registered: 2004-02-19
Posts: 1,142
Website

Re: Irm - Inverse rm

lucke wrote:

Incidentally, zsh has something like that built in.

You just use "rm ^foobar" (or "rm ^(foo1|foo2)") and it erases everything except that. And it's not limited to rm.

Awesome. Thanks for the tip. zsh++  8)


·¬»· i am shadowhand, powered by webfaction

Offline

#5 2006-10-09 07:47:13

lucke
Member
From: Poland
Registered: 2004-11-30
Posts: 4,018

Re: Irm - Inverse rm

shadowhand wrote:

Awesome. Thanks for the tip. zsh++  8)

Another great feature of zsh (which you're perhaps not familiar with) is "**", which navigates through all the subdirectories - for one, it's more handy than find when searching for filenames ;-)

% ls /lib/modules/2.6.18-ARCH/**/*nvidia*                                                        
/lib/modules/2.6.18-ARCH/kernel/drivers/char/agp/nvidia-agp.ko  /lib/modules/2.6.18-ARCH/kernel/drivers/video/nvidia.ko

Sorry for hijacking the thread, sweiss. Couldn't resist sharing with my favourite features.

Offline

#6 2006-10-10 21:04:39

sweiss
Member
Registered: 2004-02-16
Posts: 635

Re: Irm - Inverse rm

Not a problem at all. Perhaps I should too take the plunge and start using ZSH.

Does it have any noticeable drawbacks?

Offline

#7 2006-10-10 21:17:51

lucke
Member
From: Poland
Registered: 2004-11-30
Posts: 4,018

Re: Irm - Inverse rm

The only drawback is that it takes some time and effort to discover all the (great) features ;-)

Offline

#8 2006-10-13 17:57:54

headhunter
Member
Registered: 2006-07-18
Posts: 38

Re: Irm - Inverse rm

Yeah, ZSH is really great if you have the right configuration for it. Takes some time to setup, but once you're used to it you'll never want to use a bash again wink

Offline

#9 2006-10-13 20:43:30

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: Irm - Inverse rm

Gonna hijack a bit:

lucke wrote:
% ls /lib/modules/2.6.18-ARCH/**/*nvidia*                                                        
/lib/modules/2.6.18-ARCH/kernel/drivers/char/agp/nvidia-agp.ko  /lib/modules/2.6.18-ARCH/kernel/drivers/video/nvidia.ko

While this is a cool feature, the unintuitiveness and non-portability bothers me...

find /lib/modules/2.6.18-ARCH -name *nvidia*

works everywhere and gives you more options.... I mean, for example:

find /lib/modules/2.6.18-ARCH -iname *nvidia* -delete

iname is case-insensitive and -delete deletes them - try doing that with shell features (zsh OR bash) and it's a PITA

Offline

#10 2006-10-13 21:05:22

lucke
Member
From: Poland
Registered: 2004-11-30
Posts: 4,018

Re: Irm - Inverse rm

phrakture wrote:

try doing that with shell features (zsh OR bash) and it's a PITA

setopt nocaseglob
rm /lib/modules/2.6.18-ARCH/**/*nvidia*

I dare say that once nocaseglob is set, it's even more simple/intuitive than find. To each it's own. Find is indeed a great and powerful tool, but zsh has its advantages too - ability to use globbing for _any_ CLI operation (ls, rm, grep et al.) is obviously a nice thing. And it allows to distunguish files with different rights/directories/symlinks as well, bringing it even closer to find's abilities. But actually - they're quite complementary.

Yay for choice!

Offline

Board footer

Powered by FluxBB