0

I have some files in a directory that that all contain either the string "HG-U133A", or "HG-U133B". I'd like to write a script that can go through all the files in the directory and rename all the "HG-U133A" files with an "A_" prefix, and all "HG-U133B" files with a "B_" prefix.

So if these are the files in my directory

> grep "HG-U133[AB]" *
fileA.txt: HG-U133A
fileB.txt: HG-U133A
fileC.txt: HG-U133B
fileD.txt: HG-U133A
fileE.txt: HG-U133B

I'd like to write a script that can rename these files to

> ls
A_fileA.txt
A_fileB.txt
B_fileC.txt
A_fileD.txt
B_fileE.txt

I'd really appreciate some help with this. Thank You

2 Answers 2

0

This is a portable solution that doesn't fall into the Bash pitfall number 1.

for file in *; do
  [ -f "$file" ] || continue
  grep -q -- HG-U133A "$file" && { mv -- "$file" "A_$file"; continue; }
  grep -q -- HG-U133B "$file" && mv -- "$file" "B_$file"
done

Notes:

  • * doesn't match dotfiles, but you used it in your grep invocation, so I assume the behavior fits you or you know how to change it.
  • * does match directories. Your grep was invoked without options that might make it process directories. The script skips anything that is not a regular file and the main purpose of this is to skip directories and not bother running grep for them (which would fail anyway).
  • Double dash (--) is explained here: What does -- (double-dash) mean? (also known as “bare double dash”)? It's in case any of the filenames starts with a dash. If we used ./* instead of * we wouldn't need it.
  • You said "either … or …", I interpret this as "for a given file at most one string will match". Therefore continue after the first grep. It's there to not call the second grep in vain.
  • If you expect many files with HG-U133B and only few with HG-U133A then consider testing for HG-U133B first.

Advantages:

  • portability,
  • robustness (the code should work well regardless of file names).

Disadvantage:

  • spawning at least one grep process per regular file is far from being optimal; this may slow things down if there are more than few files to inspect.
-1

The following commands in bash will do it:

for file in `grep -l HG-U133A *` ; do mv "$file" "A_$file" ; done
for file in `grep -l HG-U133B *` ; do mv "$file" "B_$file" ; done
4
  • Bash pitfall number 1. Commented Aug 14, 2019 at 17:22
  • @ZuhaibAhmed: Did this work for you?
    – harrymc
    Commented Aug 14, 2019 at 18:59
  • Yes. it did. Thank you. Although, the other answer seems to be a little more robust. Commented Aug 15, 2019 at 17:35
  • If you used it and it solved your problem, in spite of not handling cases that you didn't have, should it not get at least an upvote?
    – harrymc
    Commented Aug 15, 2019 at 18:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .