Find the answer to your Linux question:
Page 1 of 2 1 2 LastLast
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 ...
  1. #1
    Just Joined! fopetesl's Avatar
    Join Date
    Aug 2004
    Location
    N.Yorkshire UK
    Posts
    19

    Question 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.
    Code:
    for file in *.dta
    do
    cp -f $file /home/mystuff/datafile.dta
    done
    works fine for every single file in the current directory.

    However what I actually need to do is something like this
    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
    Doesn't throw any warnings except the $fileB copy fails with "can't find directory"

    In C it would be a piece of cake so there must be a way in BASH. No?

  2. #2
    Just 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.

  3. #3
    Linux Enthusiast
    Join Date
    Aug 2006
    Posts
    631
    A loop is unnecessary, try this:

    Code:
    cp -f *F.dta /home/mystuff/datafileF.dta
    cp -f *R.dta /home/mystuff/datafileR.dta
    Regards

  4. #4
    Just Joined!
    Join Date
    May 2005
    Posts
    48
    How about a function. One loop copying each file when called.

  5. #5
    scm
    scm is offline
    Linux 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.

  6. #6
    Just Joined! fopetesl's Avatar
    Join Date
    Aug 2004
    Location
    N.Yorkshire UK
    Posts
    19

    Thumbs down

    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

  7. #7
    Linux Enthusiast
    Join Date
    Aug 2006
    Posts
    631
    I'm afraid I misunderstood your question. Can you post some lines of your resultant files?

    Regards

  8. #8
    scm
    scm is offline
    Linux Engineer
    Join Date
    Feb 2005
    Posts
    1,044
    Quote Originally Posted by fopetesl View Post
    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"
    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

  9. #9
    Just Joined! fopetesl's Avatar
    Join Date
    Aug 2004
    Location
    N.Yorkshire UK
    Posts
    19

    Thumbs up Yep. That's one answer

    Thanks, scm. I manged, with some help, to sort it this way:
    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
    What I don't understand is why it works.
    For instance
    Code:
    d_file="${f_file%F.dta}D.dta"
        if [ -a "$d_file" ]; then
    has me totally bemused.
    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

  10. #10
    scm
    scm is offline
    Linux 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:
    Code:
    $ echo $HOME
    /home/mydir
    $ echo ${HOME%ir}
    /home/myd
    $ echo ${HOME%/*}
    /home
    $ echo ${HOME#*/}
    home/mydir
    $ echo ${HOME##*/}
    mydir
    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:
    d_file=$(echo $f_file | sed 's/F/D/')
    but letting the shell do the transformation is more efficient than running pipelined subprocesses.

    Any more questions?

Page 1 of 2 1 2 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...