DaemonForums  

Go Back   DaemonForums > Miscellaneous > Guides

Guides All Guides and HOWTO's.

Reply
 
Thread Tools Display Modes
Old 3rd January 2009
s0xxx's Avatar
s0xxx s0xxx is offline
Package Pilot
 
Join Date: May 2008
Posts: 193
Thanked 47 Times in 22 Posts
Default

Quote:
Originally Posted by J65nko View Post
The input was a list of files, the output should be mv commands to rename the files. The sed solution is a little bit complicated, because there is no easy way to save the original file name.
Code:
[soxxx@bsd test]$ ls lat* | sed 's/\(.*\)/mv & &/; s/-/_/; s/\(.*\) \(.*\) \(.*\)/\1 \3 \2/'
mv latest-pkg latest_pkg
mv latest-pkg-calyx latest_pkg-calyx
mv latest-pkg-esat latest_pkg-esat
mv latest-pkg-plig latest_pkg-plig
[soxxx@bsd test]$ ls lat* | sed 's/\(.*\)/mv & &/; s/-/_/; s/\(.*\) \(.*\) \(.*\)/\1 \3 \2/' | sh
[soxxx@bsd test]$ ls
latest_pkg  latest_pkg-calyx  latest_pkg-esat  latest_pkg-plig
Quote:
Originally Posted by J65nko View Post
Your one-liner does not create these 'mv' commands files, as was the requirement
Right, I wasn't thinking about 'mv' command at all!
__________________
The best way to learn UNIX is to play with it, and the harder you play, the more you learn.
If you play hard enough, you'll break something for sure, and having to fix a badly broken system is arguably the fastest way of all to learn. -Michael Lucas, AbsoluteBSD
Reply With Quote
Old 4th January 2009
TerryP's Avatar
TerryP TerryP is offline
Arp Constable
 
Join Date: May 2008
Location: USofA
Posts: 1,547
Thanked 112 Times in 104 Posts
Default

I found J65nkos way of doing it interesting, but rather involved from my point of view; and several other posts also were interested. Being rather lazy, if I wanted to generate a string of mv commands to rename a group of files based on a simple pattern search & replace, at a unix shell, I would do it with a simple for loop and sed:

Code:
for FN in `ls *-*`; do 
        mv "$FN" `echo "$FN" | sed 's/-/_/g'`
done
whitespace and proper quoting added for legibility; since I would normally do it in one line at my $USER@`hostname`$ prompt. I also would admit the "quotes" around $FN if possible. Why the for loop? Because my mind thinks of the problem like this: for each file that I want to move, move the files with 'this' part of the name changed to 'this'.


It is not an efficient way of doing it, but it is fast enough when the number of files is not huge; if they were, I would probably have fun in C (or assembly if it was truly a huge set of files...). Without the limitation of using mv, I would probably use this if not in a bourne shell:

Code:
Terry@vectra$ perl -e 'map { $on=$_; s/-/_/; rename($on, $_) or warn $!; } <*>;'
Which says the same thing that my brain does. I usually use the move() function in File::Copy, but that's about 23 more keys to press in this simple case.
__________________
My Journal

Thou shalt check the array bounds of all strings (indeed, all arrays), for surely where thou typest ``foo'' someone someday shall type ``supercalifragilisticexpialidocious''.
Reply With Quote
Old 4th January 2009
J65nko J65nko is offline
Administrator
 
Join Date: May 2008
Location: Budel - the Netherlands
Posts: 3,116
Thanked 182 Times in 149 Posts
Default

Terry, that would change 'latest-pkg-erlangen' into 'latest_pkg_erlangen" which isn't what I needed. I only wanted the first '-' to be changed into an underscore, and not all of them

Another approach is to use a numerical flag after the sed search and replacement. From sed(1)
Code:
 [2addr]s/re/replacement/flags
        [snip]
Th value of flags in the substitute function is zero or more
               of the following:
       
                     0 ... 9
                             Make the substitution only for the N'th occur-
                             rence of the regular expression in the pattern
                             space.
That allows you to use things like this:
Code:
$ echo 12345678 | sed -e 's/./#/4' 
123#5678

$ echo 12345678 | sed -e 's/../#/2' 
12#5678
In the first example, the regular expression is '.', which stands for any character. the '2' flag causes only the second whatever character to be subsituted.
The regular expression from the last example is '..', or a group of two whatever characters. So here the second pair of numbers '34' is replaced by
a '#'.

A single filename like 'latest-pkg-plig' can be converted rather easily into a 'mv latest-pkg-plig latest-pkg-plig'.
To turn this intermediate result into a meaningful mv command, we only have to change the second occurrence of '-pkg' into '_pkg'.

The first transformation and the explanation:
Code:
$ echo latest-pkg-plig | sed -e 's/^.*$/mv & & /'
mv latest-pkg-plig latest-pkg-plig

# ----------------------------------------------------
        s       : search and replace
        /       : delimiter marking start of search
        ^       : beginning of line
        .       : whatever character
        *       : zero or more of the preceding atom 
        $       : end of line
       
        /       : end of search pattern, start of replacement
                
        mv      : a 'm', 'v', and a blank  
        &       : the matched searched pattern
                : a space
        &       : the matched search pattern
                : a space
        /       : end of replacement
The last and final transformation:
Code:
echo mv latest-pkg-plig latest-pkg-plig | sed -e 's/-pkg/_pkg/2' 
mv latest-pkg-plig latest_pkg-plig

# -------------------------------
        s       : search and replace
        /       : delimiter marking start of search
        -pkg    : a sequence of '-', 'p', 'k', and  'g'
       
        /       : end of search pattern, start of replacement
       
        _pkg    : a '-', 'p', 'k' and a 'g'
       
        /       : end of replacement
        2       : only act on second occurence
Applying both transformations to some file names in file tmp:
Code:
sed -e 's/^.*$/mv & & /'  -e 's/-pkg/_pkg/2' tmp

mv NOW/latest-pkg NOW/latest_pkg 
mv NOW/latest-pkg-erlangen NOW/latest_pkg-erlangen 
mv NOW/latest-pkg-plig NOW/latest_pkg-plig
Actually my directory names were much longer and they already had hyphens in them. Applying these regexes to such a directory I still had an original backup of
Code:
$ ls  Snap2008-07-12_23.47_UTC/*-pkg* | sed -e 's/^.*$/mv & & /'  -e 's/-pkg/_pkg/2'

mv Snap2008-07-12_23.47_UTC/latest-pkg Snap2008-07-12_23.47_UTC/latest_pkg 
mv Snap2008-07-12_23.47_UTC/latest-pkg-arctic Snap2008-07-12_23.47_UTC/latest_pkg-arctic 
mv Snap2008-07-12_23.47_UTC/latest-pkg-calyx Snap2008-07-12_23.47_UTC/latest_pkg-calyx 
mv Snap2008-07-12_23.47_UTC/latest-pkg-plig Snap2008-07-12_23.47_UTC/latest_pkg-plig
As you can see this really was worth to be automated
__________________
You don't need to be a genius to debug a pf.conf firewall ruleset, you just need the guts to run tcpdump
Reply With Quote
Old 4th January 2009
TerryP's Avatar
TerryP TerryP is offline
Arp Constable
 
Join Date: May 2008
Location: USofA
Posts: 1,547
Thanked 112 Times in 104 Posts
Default

Quote:
Originally Posted by J65nko View Post
I only wanted the first '-' to be changed into an underscore, and not all of them
Sorry, then I'll drop the 'g' next time ;-)
__________________
My Journal

Thou shalt check the array bounds of all strings (indeed, all arrays), for surely where thou typest ``foo'' someone someday shall type ``supercalifragilisticexpialidocious''.
Reply With Quote
Old 29th October 2009
DNAeon DNAeon is offline
Shell Scout
 
Join Date: Sep 2008
Location: Bulgaria
Posts: 138
Thanked 6 Times in 6 Posts
Default

Hi,

How about using find to rename files? I've used this command to rename all .foo files to .bar

Code:
$ ls
1.foo  2.foo  3.foo
$ find . -type f -name "*.foo" -exec echo mv {} \`basename {} .foo\`.bar \;
mv ./1.foo `basename ./1.foo .foo`.bar
mv ./2.foo `basename ./2.foo .foo`.bar
mv ./3.foo `basename ./3.foo .foo`.bar
Then just feed it to the shell:
Code:
$ find . -type f -name "*.foo" -exec echo mv {} \`basename {} .foo\`.bar \; | sh
$ ls
1.bar  2.bar  3.bar
I think with a little modification and it can fit in any situation for renaming files.
__________________
"I never think of the future. It comes soon enough." - A.E

Useful links: FreeBSD Handbook | FreeBSD Developer's Handbook | The Porter's Handbook | PF User's Guide | unix-heaven.org
Reply With Quote
Old 15th October 2010
Carpetsmoker's Avatar
Carpetsmoker Carpetsmoker is offline
Real Name: Martin
Old man from scene 24
 
Join Date: Apr 2008
Location: Eindhoven, Netherlands
Posts: 2,051
Thanked 198 Times in 156 Posts
Default

I just discovered that on the Linux system at work here has the "rename" command.

According to the manpage it's part of the "util-linux-ng" package.

Code:
RENAME(1)                  Linux Programmer’s Manual                 RENAME(1)



NAME
       rename - Rename files

SYNOPSIS
       rename from to file...
       rename -V

DESCRIPTION
       rename will rename the specified files by replacing the first occurrence of from in their name by to.


       -V, --version
              Display version information and exit.


       For example, given the files
              foo1, ..., foo9, foo10, ..., foo278, the commands

              rename foo foo0 foo?
              rename foo foo0 foo??

       will turn them into foo001, ..., foo009, foo010, ..., foo278.

       And
              rename .htm .html *.htm

       will fix the extension of your html files.


SEE ALSO
       mmv(1), mv(1)

AVAILABILITY
       The rename command is part of the util-linux-ng package and is available from ftp://ftp.kernel.org/pub/linux/utils/util-linux-
       ng/.



                                1 January 2000                       RENAME(1)
Seems to be installed by default on fedora core 11.

For example to replace all underscores with a plus: $ rename '_' '+' *

One page I found on the internet (Which is about something different entirly and just mentions this command) used a regular expression, but that doesn't seem to work for me. Didn't research it.
__________________
UNIX was not designed to stop you from doing stupid things, because that would also stop you from doing clever things.
Reply With Quote
Old 15th October 2010
IdOp's Avatar
IdOp IdOp is offline
Too dumb for a smartphone
 
Join Date: May 2008
Location: twisting on the daemon's fork(2)
Posts: 534
Thanked 14 Times in 13 Posts
Default

That rename command also comes with Slackware, and can be pretty handy. I missed having it on NetBSD, so I wrote a bash script to do the similar thing. It's attached below for anyone who is very bored. It seems to work, but hasn't been heavily used, no warranty. Probably has bash-isms.

It uses sed, but only in the most mundane way.
Attached Files
File Type: gz rename.sh.gz (617 Bytes, 35 views)
Reply With Quote
Reply

Tags
bre, regular expressions, vils

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Cleaning Portsnap files in /var/db/portsnap/files bram85 FreeBSD Ports and Packages 2 5th October 2009 09:54 AM
PHP regular expression help cajunman4life Programming 2 16th August 2008 05:17 PM
How to sync files over ftp graudeejs FreeBSD General 4 4th August 2008 10:18 PM
Mount filesystem with a regular user ivanatora FreeBSD General 15 30th July 2008 08:51 AM
are you an former bsdforum regular? ephemera Off-Topic 18 28th July 2008 12:57 PM


All times are GMT. The time now is 02:42 PM.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content copyright © 2007-2010, the authors
Daemon image copyright ©1988, Marshall Kirk McKusick