DevinG
DevinG

Reputation: 341

How to write unix regular expression to select for specific files in a cp for-loop

I've got a directory with a bunch of files. Instead of describing the filenames and extensions, I'll just show you what is in the directory:

P01_1.atag  P03_3.tgt   P05_6.src   P08_3.atag  P10_5.tgt
P01_1.src   P03_4.atag  P05_6.tgt   P08_3.src   P10_6.atag
P01_1.tgt   P03_4.src   P06_1.atag  P08_3.tgt   P10_6.src
P01_2.atag  P03_4.tgt   P06_1.src   P08_4.atag  P10_6.tgt
P01_2.src   P03_5.atag  P06_1.tgt   P08_4.src   P11_1.atag
P01_2.tgt   P03_5.src   P06_2.atag  P08_4.tgt   P11_1.src
P01_3.atag  P03_5.tgt   P06_2.src   P08_5.atag  P11_1.tgt
P01_3.src   P03_6.atag  P06_2.tgt   P08_5.src   P11_2.atag
P01_3.tgt   P03_6.src   P06_3.atag  P08_5.tgt   P11_2.src
P01_4.atag  P03_6.tgt   P06_3.src   P08_6.atag  P11_2.tgt
P01_4.src   P04_1.atag  P06_3.tgt   P08_6.src   P11_3.atag
P01_4.tgt   P04_1.src   P06_4.atag  P08_6.tgt   P11_3.src
P01_5.atag  P04_1.tgt   P06_4.src   P09_1.atag  P11_3.tgt
P01_5.src   P04_2.atag  P06_4.tgt   P09_1.src   P11_4.atag
P01_5.tgt   P04_2.src   P06_5.atag  P09_1.tgt   P11_4.src
P01_6.atag  P04_2.tgt   P06_5.src   P09_2.atag  P11_4.tgt
P01_6.src   P04_3.atag  P06_5.tgt   P09_2.src   P11_5.atag
P01_6.tgt   P04_3.src   P06_6.atag  P09_2.tgt   P11_5.src
P02_1.atag  P04_3.tgt   P06_6.src   P09_3.atag  P11_5.tgt
P02_1.src   P04_4.atag  P06_6.tgt   P09_3.src   P11_6.atag
P02_1.tgt   P04_4.src   P07_1.atag  P09_3.tgt   P11_6.src
P02_2.atag  P04_4.tgt   P07_1.src   P09_4.atag  P11_6.tgt
P02_2.src   P04_5.atag  P07_1.tgt   P09_4.src   P12_1.atag
P02_2.tgt   P04_5.src   P07_2.atag  P09_4.tgt   P12_1.src
P02_3.atag  P04_5.tgt   P07_2.src   P09_5.atag  P12_1.tgt
P02_3.src   P04_6.atag  P07_2.tgt   P09_5.src   P12_2.atag
P02_3.tgt   P04_6.src   P07_3.atag  P09_5.tgt   P12_2.src
P02_4.atag  P04_6.tgt   P07_3.src   P09_6.atag  P12_2.tgt
P02_4.src   P05_1.atag  P07_3.tgt   P09_6.src   P12_3.atag
P02_4.tgt   P05_1.src   P07_4.atag  P09_6.tgt   P12_3.src
P02_5.atag  P05_1.tgt   P07_4.src   P10_1.atag  P12_3.tgt
P02_5.src   P05_2.atag  P07_4.tgt   P10_1.src   P12_4.atag
P02_5.tgt   P05_2.src   P07_5.atag  P10_1.tgt   P12_4.src
P02_6.atag  P05_2.tgt   P07_5.src   P10_2.atag  P12_4.tgt
P02_6.src   P05_3.atag  P07_5.tgt   P10_2.src   P12_5.atag
P02_6.tgt   P05_3.src   P07_6.atag  P10_2.tgt   P12_5.src
P03_1.atag  P05_3.tgt   P07_6.src   P10_3.atag  P12_5.tgt
P03_1.src   P05_4.atag  P07_6.tgt   P10_3.src   P12_6.atag
P03_1.tgt   P05_4.src   P08_1.atag  P10_3.tgt   P12_6.src
P03_2.atag  P05_4.tgt   P08_1.src   P10_4.atag  P12_6.tgt
P03_2.src   P05_5.atag  P08_1.tgt   P10_4.src
P03_2.tgt   P05_5.src   P08_2.atag  P10_4.tgt
P03_3.atag  P05_5.tgt   P08_2.src   P10_5.atag
P03_3.src   P05_6.atag  P08_2.tgt   P10_5.src

I have a file that is just outside of this directory that I need to copy to all of the files that end with "_1.src" inside the directory.

I'm working with unix in the Terminal app, so I tried writing this for loop, but it rejected my regular expression:

for .*1.src in ./ 
> do
> cp ../1.src
> done

I've only written regular expressions in Python before and have minimal experience, but I was under the impression that .* would match any combination of characters. However, I got the following error message:

-bash: `.*1.src': not a valid identifier

I then tried the same for loop with the following regular expression:

^[a-zA-Z0-9_]*1.src$

But I got the same error message:

-bash: `^[a-zA-Z0-9_]*1.src$': not a valid identifier

I tried the same regular expression with and without quotation marks, but it always gives the same 'not a valid identifier' error message.

Upvotes: 1

Views: 411

Answers (4)

DevinG
DevinG

Reputation: 341

Thanks to everyone; this is what ended up working:

for x in `echo ./P[0-9]*_1.src`
> do
> cp ../1.src "$x"
> done

This loop allowed me to copy the contents of the one file to all of the files in the subdirectory that ended with "_1.src"

Upvotes: 1

vintnes
vintnes

Reputation: 2030

Please correct me if your goal is something other than

"overwrite many existing files sharing a common suffix with the contents of a single file"

find /path/to/dest_dir -type f -name "*_1.src" |xargs -n1 cp /path/to/source_file

Note that without the -maxdepth 1 option, find will recurse through your destination directory.

Upvotes: 0

Bayou
Bayou

Reputation: 3441

Tested on Bash 4.4.12, the following is possible:

$ for i in ./*_1.src; do echo "$i" ; done

This will echo every file ending with _1.src to the screen, thus moving it will be possible as well.

$ mkdir tmp
$ for i in ./*_1.src; do mv "$i" tmp/.; done

I've tested with the following data:

$ touch P{1,2}{0,1,2}_{0..6}.{src,tgt,atag}
$ ls
P10_0.atag  P10_5.src   P11_3.tgt   P12_2.atag  P20_0.src   P20_5.tgt   P21_4.atag  P22_2.src
P10_0.src   P10_5.tgt   P11_4.atag  P12_2.src   P20_0.tgt   P20_6.atag  P21_4.src   P22_2.tgt
P10_0.tgt   P10_6.atag  P11_4.src   P12_2.tgt   P20_1.atag  P20_6.src   P21_4.tgt   P22_3.atag
P10_1.atag  P10_6.src   P11_4.tgt   P12_3.atag  P20_1.src   P20_6.tgt   P21_5.atag  P22_3.src
P10_1.src   P10_6.tgt   P11_5.atag  P12_3.src   P20_1.tgt   P21_0.atag  P21_5.src   P22_3.tgt
P10_1.tgt   P11_0.atag  P11_5.src   P12_3.tgt   P20_2.atag  P21_0.src   P21_5.tgt   P22_4.atag
P10_2.atag  P11_0.src   P11_5.tgt   P12_4.atag  P20_2.src   P21_0.tgt   P21_6.atag  P22_4.src
P10_2.src   P11_0.tgt   P11_6.atag  P12_4.src   P20_2.tgt   P21_1.atag  P21_6.src   P22_4.tgt
P10_2.tgt   P11_1.atag  P11_6.src   P12_4.tgt   P20_3.atag  P21_1.src   P21_6.tgt   P22_5.atag
P10_3.atag  P11_1.src   P11_6.tgt   P12_5.atag  P20_3.src   P21_1.tgt   P22_0.atag  P22_5.src
P10_3.src   P11_1.tgt   P12_0.atag  P12_5.src   P20_3.tgt   P21_2.atag  P22_0.src   P22_5.tgt
P10_3.tgt   P11_2.atag  P12_0.src   P12_5.tgt   P20_4.atag  P21_2.src   P22_0.tgt   P22_6.atag
P10_4.atag  P11_2.src   P12_0.tgt   P12_6.atag  P20_4.src   P21_2.tgt   P22_1.atag  P22_6.src
P10_4.src   P11_2.tgt   P12_1.atag  P12_6.src   P20_4.tgt   P21_3.atag  P22_1.src   P22_6.tgt
P10_4.tgt   P11_3.atag  P12_1.src   P12_6.tgt   P20_5.atag  P21_3.src   P22_1.tgt   P10_5.atag  
P11_3.src   P12_1.tgt   P20_0.atag  P20_5.src   P21_3.tgt   P22_2.atag

Upvotes: 1

ForceBru
ForceBru

Reputation: 44838

Apparently, my previous answer didn't work. But this seems to:

$ for x in `echo ./P[01][012]_1.src`; do echo "$x"; done
./P01_1.src
./P02_1.src

So, when you run this echo alone, this pattern gets expanded into many names:

$ echo ./P[01][012]_1.src  # note that the 'regex' is not enclosed in quotes
./P01_1.src ./P02_1.src

And then you can iterate over these names in a loop.

BTW, as noted in the comments, you don't even need that echo, so you can plug the pattern right into the loop:

for x in ./P[01][012]_1.src; do echo "$x"; done

Upvotes: 0

Related Questions