Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Renaming all files in a directory

by Aldebaran (Curate)
on Feb 02, 2021 at 03:17 UTC ( [id://11127788]=perlmeditation: print w/replies, xml ) Need Help??

I'm so relieved to be back at my keyboard, with a roof over my head, fridge full of food, and plentiful water of varied temperature. I was feeling kind of stuck because I had a repository that I had downloaded that didn't have the proper credentials, and it was preventing updating. I got that all cleared away, so now I have:

$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.2 LTS Release: 20.04 Codename: focal $

One of the first things I'll do is create a webpage describing the trip, and that is going to require that a bunch of odd images gets herded to the net, with an exact number of corresponding captions. For this task, I find that I can really economize on GUI events with perl and a little skill on the command line.

But I'm one of those guys who would make every mistake in the book if I started at square one. I know that I had a thread some time back called renaming all files in a directory. I tried to search for this with keywords but had to resort to scrolling through my writeups back to 2012. I was gonna complain that the search didn't work. However, I had searched for the word 'rename' not 'renaming', and I realize that the problem is not with the software.

I tried one of the answers I hadn't used before:

ls | perl -nle 'BEGIN {$counter=0}; $old=$_;$new="image"."$counter"." +.jpg"; +rename($old,$new);$counter++;' $

That command didn't work at first, but I could get my way to one that did because what exists between single quotations is lexical perl that I understand. And gosh, I've been pretty diligent about studying this including taking in Util's talk at 2020 perl conference, which helped me understand how people "get there on the command line."

$ ls | perl -nle 'BEGIN {$counter=0}; $old=$_;$new="image"."$counter". +"jpg"; > +rename($old,$new);$counter++;' $ ls | perl -nle 'BEGIN {$counter=0}; $old=$_;$new="image"."$counter". +".jpg"; +rename($old,$new);$counter++;' $

and voila...

$ pwd /home/hogan/6.scripts.personal/1.umatilla.1./template_stuff/aimages $ ls image0.jpg image12.jpg image15.jpg image3.jpg image6.jpg image9. +jpg image10.jpg image13.jpg image1.jpg image4.jpg image7.jpg image11.jpg image14.jpg image2.jpg image5.jpg image8.jpg $

Another modification gets my captions looking all uniform, so I know I've got a bijection going:

ls | perl -nle 'BEGIN {$counter=0}; $old=$_;$new="caption"."$counter". +".txt"; +rename($old,$new);$counter++;'
$ pwd /home/hogan/6.scripts.personal/1.umatilla.1./template_stuff/captions $ ls caption0.txt caption13.txt caption2.txt caption6.txt caption10.txt caption14.txt caption3.txt caption7.txt caption11.txt caption15.txt caption4.txt caption8.txt caption12.txt caption1.txt caption5.txt caption9.txt $

Now I know that my data will be well-conditioned for use by other scripts to get it onto the net.

This was just my day in having perl making something easier....

Replies are listed 'Best First'.
Re: Renaming all files in a directory
by eyepopslikeamosquito (Archbishop) on Feb 02, 2021 at 05:27 UTC

      I'm pretty sure I've been schlepping this one along in my homedir as ~/bin/rename for well over two decades now that's genesis is about six years after the original.

      The cake is a lie.
      The cake is a lie.
      The cake is a lie.

Re: Renaming all files in a directory
by jwkrahn (Abbot) on Feb 02, 2021 at 04:32 UTC

    That may not work correctly, depending on what characters are in the file name:

    $ ls -l total 0 -rw-r--r-- 1 john john 0 Feb 1 20:23 four -rw-r--r-- 1 john john 0 Feb 1 20:23 one -rw-r--r-- 1 john john 0 Feb 1 20:23 two ? three $ ls | perl -nle 'BEGIN { $counter = 0 }; $old = $_; $new = "caption" +. "$counter" . ".txt"; rename( $old, $new ); $counter++;' $ ls -l total 0 -rw-r--r-- 1 john john 0 Feb 1 20:23 caption0.txt -rw-r--r-- 1 john john 0 Feb 1 20:23 caption1.txt -rw-r--r-- 1 john john 0 Feb 1 20:23 two ? three

    Better to use perl's built-in glob function:

    $ ls -l total 0 -rw-r--r-- 1 john john 0 Feb 1 20:28 four -rw-r--r-- 1 john john 0 Feb 1 20:28 one -rw-r--r-- 1 john john 0 Feb 1 20:28 two ? three $ perl -e '$counter = 0; for ( <*> ) { $old = $_; $new = "caption" . " +$counter" . ".txt"; rename( $old, $new ); $counter++; }' $ ls -l total 0 -rw-r--r-- 1 john john 0 Feb 1 20:28 caption0.txt -rw-r--r-- 1 john john 0 Feb 1 20:28 caption1.txt -rw-r--r-- 1 john john 0 Feb 1 20:28 caption2.txt
      Why needs the counter be inside a BEGIN block?
        In this example, perl is reading line by line, (perl -nle ...) and you want the counter to only be initialized (once) at the start of the script.
Re: Renaming all files in a directory -- perl -n -p and empty files oneliner
by Discipulus (Canon) on Feb 02, 2021 at 11:35 UTC
    hello Aldebaran,

    you can avoid the oneliner BEGIN block using the Maori-farewell like in perl -M'5; $counter=0' -nle ...

    But you can avoid the counter at all:

    >perl -nlE "say sprintf qq(caption%03s.txt),$count++" one.txt two.txt + three.txt caption000.txt caption001.txt caption002.txt

    PS you get the filename currently processed in $ARGV so you can play with it:

    >perl -nlE "say sprintf q(caption%03s.txt),$1 if $ARGV =~ /.*([\d]+).* +/" one01.txt one02.txt caption001.txt caption002.txt

    PPS note that perl -n and perl -p both skip empty files!

    ls -l -rw-rw-r-- 1 io io 0 feb 2 13:28 one.txt -rw-rw-r-- 1 io io 0 feb 2 13:28 three.txt -rw-rw-r-- 1 io io 20 feb 2 13:37 two.txt perl -nlE 'say "processed $ARGV" if eof' *.txt processed two.txt

    PPPS after choroba's nice below response I cant resist to update the title and to try it:

    perl -MTie::Scalar -M"5;{package SN; use parent -norequire => 'Tie::S +tdScalar';sub FETCH {print qq(Opening ${$_[0]}); ${$_[0]}}}; tie $ARG +V, SN" -nlE "say qq(\tprocessed $ARGV) if eof" 001.txt 002.txt 003.txt Opening 001.txt Opening 002.txt Opening 002.txt processed 002.txt Opening 003.txt

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
      > note that perl -n and perl -p both skip empty files!

      They don't, but that part of code is not exposed to us to insert our own code into. Or is it?

      #!/usr/bin/perl -n use warnings; use strict; { package File::ShowName; use Tie::Scalar; use parent -norequire => 'Tie::StdScalar'; sub FETCH { print STDERR "Opening ${ $_[0] }.\n"; ${ $_[0] } } } BEGIN { tie $ARGV, 'File::ShowName' } print;

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Renaming all files in a directory
by choroba (Cardinal) on Feb 02, 2021 at 13:19 UTC
    If you don't want to use Perl's glob, use the shell's globbing instead of parsing the output of ls.
    perl -we 'rename $_, "image" . $counter++ . ".jpg" for @ARGV' *
    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://11127788]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (6)
As of 2024-04-18 02:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found