2

I am writing a script to rename my files, The current syntax for filename is program 1.c and I want to change this to cprogram-program1.c.

I am unable to get this format. Few conditions for simplicity are:

  • assume that there are only 10 files i.e: 0,1,2,3..9

My procedure to achieve this:

  • First we need to filter the files to find out files that follow the given pattern

  • Then we need to filter the filename into substrings ignorer to verify whether they are in a proper format

  • If they are in a proper format, then we can edit the filename in the way we need it.

I am stuck on step 1 and 2, this is sort of what I am doing:

for fn in *; do --> this loops over the files program=${fn:0:7} number=${..} --> number between 0 and 9 extension=${..} --> gets file extension like .c if [ "$program" == "program" ] then if [ "$number" -ge 0 ] && [ "$number" -le 9 ] then if [ "$extension" == ".c" ] then --> edit code fi fi fi done 

My problem: I have tried many permutations of the above example, but I am unable to get what I want. Any help, simple method of doing this would be highly appreciated.

Thanks

3
  • Do the current filenames really have a space; eg, program 1.c?CommentedOct 1, 2015 at 2:55
  • @jasonwryan yeah there is a space
    – Mathew
    CommentedOct 1, 2015 at 2:56
  • for file in *.c; do [[( -f $file && $file =~ program )]] && echo cprogram-"${file/ /}"; doneCommentedOct 1, 2015 at 3:04

2 Answers 2

1
for fn in * do case $fn in (program*[1-8].c) : do something;; (other*program*[09].ext) : do something with this match;; (this*match|*or*|*any*"$of"*these*matches) : do something with these matches : do as many lines as you want;; (*) : catch all last default match esac done 

A commonly used technique in case statements is to prune unwanted matches with more specific patterns than your generally desired pattern. For example:

for fn in * do case $fn in (*[0-9][0-9].c) ;; (program*[1-8].c) echo mv "$fn" "${fn%???}0${fn#"${fn%???}"}" esac done 

In the above example the first *[0-9][0-9].c pattern matches all $fn values where two or more digits might occur to the left of the extension. The execution block for those matches is empty - null - nothing at all happens when a match is found. Most importantly, though, because case statements work top-down, what this means is the only results ever matched for the action block will contain only the one digit to the left of the extension, and the example echo command would insert a 0 before each and every one of those occurring between 1 and 8.

3
  • thanks for the approach, I am having trouble executing the case statement, this example doesn't return anything : for fn in * do case $fn in (*) : echo "hi" ;; esac done
    – Mathew
    CommentedOct 1, 2015 at 4:07
  • ^ can you please tell me what the issue might be
    – Mathew
    CommentedOct 1, 2015 at 4:08
  • @Mathew - yeah, of course. The issue is the : null command. I prefixed all of the command statements with : true on purpose - so nothing would happen. It's all a do nothing there, but if you remove your : colon, your command will print hi.
    – mikeserv
    CommentedOct 1, 2015 at 4:12
0

Alternatively, dispense with the script and use a rename tool instead.

Frustratingly there are (at least) two different instances of rename depending on your distribution. On some systems the Perl version may be called prename. However, you can tell which one you have by running rename -n ';' /dev/null. If nothing happens you have the Perl version. If you get an error it's the other one.

The current syntax for filename is program 1.c and I want to change this to cprogram-program1.c. Assume that there are only 9 files i.e: 0,1,2,3..9

  1. The Perl-based rename (prename)

    rename 's/^/cprogram-/; s/\s//' program\ ?.c 
  2. The other rename

    rename -v 'program ' cprogram-program program\ ?.c 

    You must log in to answer this question.

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.