3

I files which a system generates with a generic file name. I want to have a script I can run which scans these files for the second instance of the word ProcID (after the word ProcID is a number) and then renames the file with the ProcID number. Currently I have the following:

FILEPATH; awk -F '[:)]' '/ProcID./{printf "mv %s %s.txt\n", FILENAME, $2 | "/bin/sh"; nextfile}' O*.TXT

For example, script scans files and finds second instance of (ProcID:0000014778) and then it renames the file with this Proc ID number.

The script above finds only the first instance, and therefore files are being renamed before the system has finished outputting to the file.

12
  • Do you need to set the extension, or just the id? Any risk on dupe names to take into account? – Jacob Vlijm Jan 27 '17 at 16:59
  • Hi IanG, just curious, but did you notice the answer(s)? – Jacob Vlijm Jan 28 '17 at 16:06
  • 2
    Can you explain why no python? You asked I want to have a script. If one or more languages are excluded, please add it to your question. – Jacob Vlijm Jan 30 '17 at 11:34
  • 2
    Both Python 2 and Python 3 are widely used today, including for system administration, so you might want to install Python 3. It shouldn't interfere with your Python 2 installation (if any) at all. I think every Ubuntu system has at least one of python-minimal or python3-minimal preinstalled, though I'm unsure if this is universally true on Ubuntu Core. Either way, you should be able to get a fully functional Python 3 installation by installing the python3 package, for example by running sudo apt-get update and then sudo apt-get install python3. – Eliah Kagan Jan 30 '17 at 13:23
  • 1
    @IanG Python 2.4 is ancient (2003-2006) and is indicative that you're on an ancient (and long-unsupported) version of Ubuntu, or something else entirely, similarly crusty. For things to be answerable by our users —and useful to future users— we require you're using a supported version of Ubuntu and all the shiny things that come with it. We occasionally look the other way, but if you really are on something that old, a base prerequisite to any answer you get is going to be upgrading. – Oli Jan 30 '17 at 16:42
5

The script below renames all files in a directory, to the id in the second found string, starting with ProcID::

1. Renaming to the id in the second matching string (literally; no extension)

enter image description here

#!/usr/bin/env python3
import shutil
import os
import sys

dr = sys.argv[1]

for f in os.listdir(dr):
    file = os.path.join(dr, f)
    try:
        # only rename if the second instance exists
        new = [s for s in open(file).read().split() if s.startswith("(ProcID:")][1]
    except (IndexError, IsADirectoryError):
        pass
    else:
        # rename the file
        shutil.move(file, os.path.join(dr, new.split(":")[-1].strip()[:-1]))

To use

  1. Copy the script into an empty file, save it as rename_files.py
  2. run it with the directory as argument:

    python3 /path/to/rename_files.py /path/to/directory_with_files
    

Notes

  • The script assumes the (exact) format: ProcID:0000014778
  • The script will not rename files if there is no second instance of ProcID (or none at all)

2. Only rename .txt files, and keep the extension

...Then use the version below, it will only rename .txt files and keep the extension in the renamed file. Usage is exactly the same.

#!/usr/bin/env python3
import shutil
import os
import sys

dr = sys.argv[1]

for f in os.listdir(dr):
    file = os.path.join(dr, f)
    try:
        # only rename is the second instance exists
        new = [s for s in open(file).read().split() if all([
            s.startswith("(ProcID:"), f.endswith(".txt")
            ])][1]
    except (IndexError, IsADirectoryError):
        pass
    else:
        shutil.move(file, os.path.join(dr, new.split(":")[-1].strip()[:-1]+".txt"))

What the script does

  • it lists the files in the directory:

    for f in os.listdir(dr)
    
  • lists the strings inside the file, starting with ProcID:

    new = [s for s in open(file).read().split() if s.startswith("(ProcID:")][1]
    

    The ending [1] extracts the second occurrence of strings, starting with ProcID: ([0] is the first one)

  • splits of the id:

    new.split(":")[-1].strip()
    
  • and renames the file, using the id:

    shutil.move(file, os.path.join(dr, new.split(":")[-1].strip()[:-1]))
    

EDIT

Python2 version of script 1. OP turns out to have python2 installed, which requires IOError instead of IsADirectoryError to prevent errors in case the script runs into a directory instead of a file.

#!/usr/bin/env python
import shutil
import os
import sys

dr = sys.argv[1]

for f in os.listdir(dr):
    file = os.path.join(dr, f)
    try:
        # only rename if the second instance exists
        new = [s for s in open(file).read().split() if s.startswith("(ProcID:")][1]
    except (IndexError, IOError):
        pass
    else:
        # rename the file
        shutil.move(file, os.path.join(dr, new.split(":")[-1].strip()[:-1]))

...and for being complete, a python2 version of the second script:

#!/usr/bin/env python
import shutil
import os
import sys

dr = sys.argv[1]

for f in os.listdir(dr):
    file = os.path.join(dr, f)
    try:
        # only rename is the second instance exists
        new = [s for s in open(file).read().split() if all([
            s.startswith("(ProcID:"), f.endswith(".txt")
            ])][1]
    except (IndexError, IOError):
        pass
    else:
        shutil.move(file, os.path.join(dr, new.split(":")[-1].strip()+".txt"))
6
  • Ran: python2 /PATH/rename_files.py /PATH/TO/DIRECTORY_WITH_FILES seems to run, but no change to the file names. – IanG Jan 30 '17 at 14:34
  • Then could you give me the content of one of the files (just the relevant strings)? There must be an issue with that, else the files are renamed for sure. – Jacob Vlijm Jan 30 '17 at 14:35
  • Here is an example: UCXJLI3M Version 6.00A patchlevel 907-602 JOB 42349166 (ProcID:0000027096) START AT 30.01.2017 / 10:00:02 ** UTC TIME 30.01.2017 / 10:00:02 TEXT=" Job started 0042346870 PROCESSNAME JOBNAME /PATH/TO/JOB ********************************************************************* **** UCXJLI3M Version 6.00A patchlevel 907-602 **** ** JOB 42349166 (ProcID:0000014778) ENDED AT 30.01.2017 / 10:00:03 ** ** UTC TIME 30.01.2017 / 10:00:03 ** ** TEXT=" Job ended " RETCODE=00 ** – IanG Jan 30 '17 at 14:39
  • Yep, got it, will edit. Done, please try again. Wait, still need to edit out ). Not sure if I'll make it... need to teach in a minute. – Jacob Vlijm Jan 30 '17 at 14:40
  • Traceback (most recent call last): File "/PATH/rename_files.py", line 12, in ? new = [s for s in open(file).read().split() if all([ NameError: name 'all' is not defined – IanG Jan 30 '17 at 15:34
2

Your original script was kind of close, and it can be edited to count the instances via if statement and a counter variable:

FILEPATH; awk -F '[:)]' '/ProcID./{ count++; if(count == 2 ){ printf "mv %s %s.txt\n", FILENAME, $2 | "/bin/sh"; nextfile}}' O*.TXT

In case you're seeking alternative solution, you could use this Perl script:

#!/usr/bin/env perl
use strict;
use warnings;

my $cnt=0;
open(my $fh,'<',$ARGV[0]) or die "open failed";
my $new_name;
while ( my $line = <$fh> ){
    $cnt+=1 if $line =~ /ProcID/;
    if($cnt==2){
        chomp $line;
        my @words = split(/[:)]/,$line); 
        $new_name = $words[1] . ".TXT";
        last;
    }
}
if (defined $new_name){
   rename $ARGV[0], $new_name;
}
close($fh)

Sample run:

$ ls
0000014777.TXT  rename_by_procid.pl*

$ ./rename_by_procid.pl 0000014777.TXT                                                                                                

$ ls
0000014778.TXT  rename_by_procid.pl*
1
  • HI. Thanks for this. I tried the following, which does work, but only does one file in a directory, it does not search all files and change. FILEPATH; awk -F '[:)]' '/ProcID./{ count++; if(count == 2 ){ printf "mv %s %s.txt\n", FILENAME, $2 | "/bin/sh"; nextfile}}' O*.TXT – IanG Jan 30 '17 at 8:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.