0

I have files in my home dir as

 member_net.2017-04-20.control
 member_elig_net.2017-04-20.control
 mdcr_contractr_net.2017-04-20.control

I want to rename the files to a different date like in the same dir as

 member_net.2017-04-21.control
 member_elig_net.2017-04-21.control
 mdcr_contractr_net.2017-04-21.control

These files are not of 0 bytes.

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
  • assuming you want to rename all the files having date format as yyyy-mm-dd to current date right ? – Sagar Sep 29 '17 at 19:48
  • @Sagar: Not necessarily the current date I think. – NickD Sep 29 '17 at 19:59
  • Lets say my files have date as 2017-04-20, I want to rename the files to a new date i.e 2017-04-21. – Binay Mishra Sep 29 '17 at 20:08
  • Related, the answers with `s/a/b/` and Bash's `${var//a/b}` work with longer strings than single characters: https://unix.stackexchange.com/questions/19058/how-to-replace-one-char-with-another-in-all-filenames-of-the-current-directories – ilkkachu Sep 29 '17 at 20:24

4 Answers4

2

A different method is to write a shell script, e.g. in bash:

#!/bin/bash
for f in *.2017-04-20.* ;do
    mv "$f" "${f/2017-04-20/2017-04-21}"
done

It is much simpler than the other solution in this case, but I do recommend that you always keep the other solution in mind.

ilkkachu
  • 133,243
  • 15
  • 236
  • 397
NickD
  • 2,866
  • 1
  • 10
  • 21
  • Why not add this as another option in your answer above? – Hunter.S.Thompson Sep 29 '17 at 20:09
  • 1
    Maybe I should, but they seemed so different from each other and I did want to highlight the `cat command.list | bash` trick in the other answer. I hoped that that would not get lost in the noise. – NickD Sep 29 '17 at 20:21
0

With the Perl rename command:

rename -n -v 's/2017-04-20/2017-04-21/' *.control

(-n is for no-action, -v for verbose, so you can check what it does before actually running it.)

ilkkachu
  • 133,243
  • 15
  • 236
  • 397
-1

If this is a one-off, I find the following process to be the best fit between convenience and robustness:

  • Use ls with a pattern to select the files that you want and redirect the output to a file (the pattern is just an example, but it is not critical because of the next step):

    ls member_net.*.control > file.list

  • Edit file.list in your favorite editor: get rid of any files that you don't want to change (that's why the pattern above is not critical); make sure that it includes all the files that you want to change, adding any missing ones by hand if necessary; change each line from xxx to mv xxx XXX where XXX is just like xxx but with the modified date. This step depends on your editor, but can also be done by using sed on the original file and paste to paste the files together:

    sed 's/2017-04-20/2017-04-21/g' file.list > newfile.list

    paste file.list newfile.list > bothfiles.list

    sed 's/^/mv /' bothfiles.list > commands.list

  • You now should have a file commands.list that contains command lines of the form

    mv OLDNAME NEWNAME

  • Check it carefully to make sure each command line is correct and complete.

  • Then you can execute the commands by piping the file into your shell:

    cat commands.list | bash

What I find attractive is that I can check the file and make sure that it is exactly right and then without touching it at all execute all the commands in it and be sure that it will do the right thing.

This is not as general as writing a shell script, but it is often a useful technique to remember.

NickD
  • 2,866
  • 1
  • 10
  • 21
  • This will fail with filenames containing newlines or tabs, so it's not very general. Pasting commands to a shell also feels somewhat iffy, given that there's also a proper solution (in your other answer). – ilkkachu Sep 29 '17 at 20:12
  • Correct: as I said it's not a general solution, but it is a useful trick to have in one's tool belt. "Pasting commands" - did you mean "Piping commands"? If so, I disagree that it is iffy: it is actually much safer than a shell script, because I can *look* at the commands *before* I execute them. – NickD Sep 29 '17 at 20:16
  • yep, I meant piping like that. You'd need to be very careful to double check the commands, otherwise you might end up running commands from the filenames. Which would not happen with a shell script that does its job properly. – ilkkachu Sep 29 '17 at 20:20
  • I find the trick valuable in "irregular" situations where a shell script is harder to write. If it's a one-off, why bother writing the script? You'd have to write it, test it, debug it and after all this trouble throw it away. Instead, I can write a file (or better yet write a script that writes the file) that contains exactly the commands I need and pipe it into the shell - and then throw it away. – NickD Sep 29 '17 at 20:26
-1

Here is the shell script that will help you. You can choose different date. I used current date. Save the shell script as myrename.sh and call it ./myrename.sh dirname. Where dirname is the name of directory in which files will be affected.

#!/bin/bash
for i in `ls $1 | grep -E '[0-9]{4}-[0-9]{2}-[0-9]{2}'`
do
    x=`echo $i | grep -oE   '[0-9]{4}-[0-9]{2}-[0-9]{2}'`
    y=`echo $i | sed "s/$x/$(date +%F)/g"`
    mv $1/$i $1/$y 2>/dev/null #incase if old date is same as current date
done
Sagar
  • 438
  • 3
  • 11
  • Parsing the output of `ls` like that will also fail with names containing whitespace, or possibly other characters, see http://mywiki.wooledge.org/BashPitfalls#for_i_in_.24.28ls_.2A.mp3.29 – ilkkachu Sep 29 '17 at 20:15
  • Well yeah this is just the rough idea. Who said this is complete bullet proof source code. This is just to give him idea how one could do it. @ikkachu – Sagar Sep 29 '17 at 20:28