copy all files in a directory ... a little help please?

Hi everybody,

I'd like to modify this script from the script library: copy all files in a directory so that it can exclude directories and or files like you can with rsync.

It has been a long time since I've used rebol, and I was never much good at it!

Any help appreciated...

Hello @hcfe,

I'll note that this isn't really a general Rebol Q&A support forum (it's main purpose is for developers to discuss the evolution of the language).

But I'll throw in a couple of thoughts...

For the provided Rebol2 code:

copy-dir: func [source dest] [
    if not exists? dest [make-dir/deep dest]
    foreach file read source [
        either find file "/" [
            copy-dir source/:file dest/:file
        ][
            print file
            write/binary dest/:file read/binary source/:file
        ]
    ]
]

He suggests using it like:

copy-dir %pages/ %archive/

There are a few general ways you can imagine expanding this to supply more parameters to COPY-DIR..

One basic way would be to add a third parameter for any exclusions. You could make it a single value and pass "none" if you didn't want to exclude anything:

   copy-dir %pages/ %archive/ %dont-copy.txt  ; exclude last parameter

   copy-dir %pages/ %archive/ none  ; don't exclude anything

You could make this a little better by passing a block, which would then allow you to exclude multiple items:

   copy-dir %pages/ %archive/ [%dont-copy.txt %dont-copy-either.txt]

   copy-dir %pages/ %archive/ []  ; don't exclude anything

If you don't like having to pass three parameters all the time, you could make the third parameter a "refinement" which is an optional parameter, that you'd only get if you used the /EXCLUDE option in the invocation.

  copy-dir %pages/ %archive/  ; don't exclude anything

  copy-dir/exclude %pages/ %archive/ %dont-copy.txt

In Rebol2, you'd do this by defining your function spec as func [source dest /exclude exclusions], where EXCLUDE would be falsey if the refinement were not used and truthy if it is used. If truthy, then EXCLUSIONS would hold the extra parameter.

(The Ren-C evolution of Rebol3 unified refinements with their arguments, so you could just have /EXCLUDE and that would be the name of the variable if used, or an "antiform" null if it was not used.)

Another concept could be that you could forego the idea of function parameters entirely and start thinking about this as a "dialect". Maybe you even supply processing code to hook what happens.

 mysync [
     from: %pages/
     to: %archive/
     <exclude> %dont-copy.txt %dont-copy-either.txt
     <hook> %special.txt (
         print ["Special handling of" name]  ; imagine name filled as %special.txt
         if (last-modified - now) < 12:00 [  ; imagine last-modified also filled in
             return <exclude>
         ]
         print "modified long enough ago, falling through to normal copy"
     )
 ]

So I've fancifully suggested the idea that if you put a TAG! with <hook> in it then it runs some code in a PAREN! afterward (Ren-C calls expressions in parentheses GROUP!s). That code has some predefined variables filled in for you like the file's name, and when it was last modified. You might be able to get it to take certain actions by returning signals... here I'm saying you can conditionally exclude a file based on the last modified time.

To me this is the interesting potential of Rebol. And if you're not looking to wire up solutions that look like that, you're probably better served by learning a more mainstream and better documented/supported language. Certainly there are many places you can look to find implementations of rsync-like tools...!

If you're a beginner and want to get support with the basics, Red Gitter is a place where they cater more to that...and are trying to get people to use Red...which is very similar to Rebol2, but (mostly) open-source and still being developed. It's probably the best place to chat.

Here is just the neverending discussion of lots of agonizing theory and details. :dizzy_face:

1 Like

Out of curiosity… what would be the simplest way of implementing a dialect like this? I’m still not totally confident I understand how dialects are implemented, and this feels like a nice simple example for me to wrap my head around.

Sorry about that. I'll leave you guys to it. Thanks for your patient and helpful reply.

I've looked at Red, but it's not for me. Mostly open-sourced seems like bait and switch, and is still closed. Not much point in that when there are so many other options out there. Thanks again for the help and good luck. I'll probably lurk around for a while.

1 Like

I forgot to answer this. But hopefully it's mostly apparent now.

Historically, there's not a whole lot of magic to it. Really just some structural operations to pick apart and compose arrays...and PARSE was pretty much the best you had. But it had some key weaknesses, which the UPARSE design remedies.

There are helper functions for dialecting. R3-Alpha had DELECT, and @rgchris has MATCH, there are others:

Quartermaster MATCH dialect (name conflict with Ren-C)

Supposedly high-leverage is that you could pick out arrays you want to run, transform them, and EVAL them. But binding was pretty much always broken for any non-trivial usages. Ren-C has a much stronger hand here.

(Note: I've pointed out that historically a lot of the time, the developers of a Redbol (e.g. Carl, Nenad, Oldes, Karl-with-a-K) just give up and go to native code to implement a dialect. So they wind up writing a C-type program that processes the arrays. I really don't feel like that's compelling. One weak point for people who are used to XML or the DOM etc. is that because everything can be imaged in multiple locations, there are no "parent" pointers in the data structure. And I question the usefulness of things like Boron... but :man_shrugging:)

I actually don't have any big ideas about the higher-level dialecting tools. I just want to make PARSE and EVAL coherent and robust enough to build those...or whatever you want.

1 Like