tags:

views:

204

answers:

5

Hi I'm not used to do things in Bash, so I'm having some problems:

My goal is to look for special files in a folder, and if found generate some other files with the same filenames, but different extension.

Something like:

For Files-that-are-called-"SysBackup*.Now" 
do
  NewFileName = ChangeFileExt(FoundFilename),BK
  GenerateNewfile(NewFileName)
done

The above is of course dummycode, I won't bother you with the code I have done, as it is not working :-)

So the goal should be:

If the folder contains Sysbackup123.now and Sysbackup666.now, I will end up with the files Sysbackup123.bk and Sysbackup666.bk

Thank you for any help

Michael

+1  A: 

You could do something like this:

for F in SysBackup*.Now; do
    [ -f $F ] && touch $(echo "$F" | sed 's/Now$/BK/')
done

This uses echo to pass the filenames to sed, which changes the postfix string "Now" to "BK". touch creates the file, if it does not exist yet. The new file will be empty. The test [ -f $F ] ensures that only files (not directories or symlinks) are considered.

Alternatively, you can use find. An example using basename, as demonstrated in Stephen Darlington's answer:

find . -type f -iname "SysBackup*.Now" -exec sh -c "touch \$(basename '{}' .Now).BK" \;

Note that in both examples it is important to place quotes around the filenames, to ensure proper handling of filenames with spaces.

Stephan202
+8  A: 

Fairly straightforward:

for a in Sysbackup*.now;
do
  [ -f $a ] && touch $(basename $a .now).bk ;
done
Stephen Darlington
+1. Didn't know about the second argument to `basename`.
Stephan202
Bash also allows stripping characters from the end of a string with *%*. And you *probably* should get in the habit of quoting filenames: **touch "${a%.now}.bk"**
NVRAM
Hmmm, one thing: for file in Sysbackup*.now;do echo "WTF?" doneThe problem is that every time I run my script, the WTF? gets written to the screen, even though there is no Sysback.now file.I would guess (and I need) that the function only is running if there in fact IS a Sysbackup*.now file
Reiler
Stephan202
I added the check for the file before the `touch` command. (I did have that line in originally but removed it! Doh!)
Stephen Darlington
Thanks a lot, the check if it was a file did the job
Reiler
Reiler, remember to click the check-mark to this response, so that the system knows that it is the accepted answer.
Lars D
+2  A: 

This is how I do it with sh:

#!/bin/sh

for file in SysBackup*.now; do
  if [ ! -e "$file" ]; then
    continue
  fi

  base=${file##*/}
  bk=${base%.now}.bk

  touch $bk
done
Gregory Pakosz
Although I don't believe it's particularly interesting, wouldn't the solution I'm using be faster as it doesn't require to fork and invoke `basename`?
Gregory Pakosz
+2  A: 

Here's another way to do the substitution. Bash has an equivalent to sed's s/string1$/string2/ which uses the regex dollar sign to select the end of the pattern:

for a in Sysbackup*.Now;
do
  [ -f $a ] && touch "${a/%.Now/.BK}"
done

The percent sign matches at the end and a pound (#) matches at the beginning.

Dennis Williamson
You need to use **.Now** in your first line: if you match files, they will end with **.now** not **.Now** as the OP used, and as you used in your variable pattern -- and as a consequence, you'd just *touch* the original file.
NVRAM
Oops, typo, fix'd, thanks.
Dennis Williamson
As I said to *ghostdog74* - this one reason I usually avoid the *substitute* pattern, and use the *remove/append* instead: **${file%.Now}.BK** -- which will never be the same as the original filename. I once did something like this: **grep "$PATTERN" "$a" > "${a/%.Now/.BK}"** -- and consequently lost all of my data.
NVRAM
A: 

here's another way, if you don't want to use for loop and testing whether its a file or not

find /path -maxdepth 1 -type f -name "Sysbackup*now" | while read file
do
  touch "${file/%.now/.bK}"
done
ghostdog74
Not sure I like using **find** simply to avoid the no-match problem, but whatever. However, you need a dot in your *-name* argument, otherwise a file named **Sysbackup-before-snow** will be found and, since it does not end in ".now" the filename will be given, unchanged, to the **touch** program. This one reason I usually avoid the *substitute* pattern, and use the *remove/append* instead: **${file%.now}.bk** -- which will never be the same as the original filename (at least it will append a ".bk").
NVRAM