Results 1 to 10 of 12
I'm trying to write a script which loops copying dual files to another directory but (even having RTFM) I can't find a way to do it.
There doesn't seem to ...
- 12-07-2007 #1
BASH: FOR control with two variables?
I'm trying to write a script which loops copying dual files to another directory but (even having RTFM) I can't find a way to do it.
There doesn't seem to be an AND control I can use.works fine for every single file in the current directory.Code:for file in *.dta do cp -f $file /home/mystuff/datafile.dta done
However what I actually need to do is something like thisDoesn't throw any warnings except the $fileB copy fails with "can't find directory"Code:for fileA in *F.dta AND fileB in *R.dta do cp -f $fileA /home/mystuff/datafileF.dta cp -f $fileB /home/mystuff/datafileR.dta done
In C it would be a piece of cake so there must be a way in BASH. No?
- 12-07-2007 #2Just Joined!
- Join Date
- Dec 2007
- Location
- Ceredigion, Wales,UK.
- Posts
- 10
Bash: for control with two variables
As a total newbie who has written precisely one, very small working script, and a firm believer in the KISS principle, what I would do would depend on why I wanted to do it.
If for pride, then I would run the script 3 times with the -x option to see what was happening: the first time as it is, then substituting -a and && for AND. If that didn't help it would be back to tutorials, forums and googling until I found an answer. This looks a likely spot:-http://wooledge.org:8000/BashFAQ#faq24
But, if I simply needed it to work, the obvious solution would seem to be two 'for' loops.
Feel free to ignore this. I may well be talking out of the back of my neck.
- 12-07-2007 #3Linux Enthusiast
- Join Date
- Aug 2006
- Posts
- 631
A loop is unnecessary, try this:
RegardsCode:cp -f *F.dta /home/mystuff/datafileF.dta cp -f *R.dta /home/mystuff/datafileR.dta
- 12-08-2007 #4Just Joined!
- Join Date
- May 2005
- Posts
- 48
How about a function. One loop copying each file when called.
- 12-08-2007 #5Linux Engineer
- Join Date
- Feb 2005
- Posts
- 1,044
Are you trying to copy only those files with matching names ie F and R variants both exist? Your desired logic wouldn't address that even it the for condition worked the way you've coded it. What I'd do is to extract all the filenames you're interested in and strip off the [FR].dta, sort them into a unique list of names and then feed them into the loop, testing for the presence of both F and R variants before performing the copy.
- 12-08-2007 #6
scm: I'm afraid you've lost me there. You're obviously knowledgeable about BASH but you and I are talking in a different language. I can write C pretty well but BASH, though it can have similarities, is different enough to have me learn another mind set. Your suggestion seems to be overly complicated but if that's the only answer ......
I'll explain further:
I should have made it clearer that files named *F.dta need to be copied to a specific filename, always the same.
So a file originally named, say, "20071208134214F.dta" (note the date and time) would have to be copied to "AlwaysUseSameFileName_F.dta".
Similarly for the 'R' file.
I have a C program which processes the data from the two resultant files, "AlwaysUseSameFileName_F.dta" and "AlwaysUseSameFileName_R.dta"
OK I could modify the C prog but it should be easier to hack a small(?) BASH script.
waka: maybe a tiny clue?
Franklin52: That surely would copy all the files in one go? I need to process each pair of files sequentially.
Hatrick: neat and I'm beginning to think the only answer. Problem is I really don't have that much time. Maybe I'll have a panic attack instead
- 12-08-2007 #7Linux Enthusiast
- Join Date
- Aug 2006
- Posts
- 631
I'm afraid I misunderstood your question. Can you post some lines of your resultant files?
Regards
- 12-08-2007 #8Linux Engineer
- Join Date
- Feb 2005
- Posts
- 1,044
Now you've lost me.

Do you have a single file with a specific name (as your date-and-time named file) with both an F and an R suffix that you wish to copy to the "AlwaysUseSameFileName" files and then run your processing program before doing the next file? If so, I'd be inclined to do something like:
Code:for a in *_F.dta do if [ -r ${a%_F.dta}_R.dta ] then # found both an F and an R file cp -p $a /home/mystuff/AlwaysUseSameFileName_F.dta cp -p ${a%_F.dta}_R.dta /home/mystuff/AlwaysUseSameFileName_R.dta # run your processing program here fi done
- 12-08-2007 #9
Yep. That's one answer
Thanks, scm. I manged, with some help, to sort it this way:
What I don't understand is why it works.Code:for f_file in *F.dta; do d_file="${f_file%F.dta}D.dta" if [ -a "$d_file" ]; then echo "replace this with some copy operation which you like" else echo "there is no file $d_file corresponding to $f_file" fi done
For instancehas me totally bemused.Code:d_file="${f_file%F.dta}D.dta" if [ -a "$d_file" ]; then
I can't see how the parameter from $f_file is taken and converted into D.dta and hence into $d_file. Is it an increment on $f_file to find D.dta?
Whatever, it works
- 12-09-2007 #10Linux Engineer
- Join Date
- Feb 2005
- Posts
- 1,044
Welcome to the wonderful world of shell programming!
The construct ${varname%pattern} substitutes the value of the variable "varname" with the string "pattern" removed (if it exists) from the end of the variable contents. # instead of % removes "pattern" from the start of the variable contents. Using ## or %% does a "greedy" match, the single variants do a minimal match. You can play with the echo command to get the hang of it:
In the d_file assignment we're loading d_file with the name of the file with the F.dta removed and appending D.dta to it, hence you end up with the other file name. There are other ways to do that:Code:$ echo $HOME /home/mydir $ echo ${HOME%ir} /home/myd $ echo ${HOME%/*} /home $ echo ${HOME#*/} home/mydir $ echo ${HOME##*/} mydir
but letting the shell do the transformation is more efficient than running pipelined subprocesses.Code:d_file=$(echo $f_file | sed 's/F/D/')
Any more questions?


Reply With Quote
