How to Show Folders within a Tree without Parents or Subfolders with a Regexp

Please check the FAQ (https://www.xyplorer.com/faq.php) before posting a question...
Dustydog
Posts: 315
Joined: 13 Jun 2016 04:19

How to Show Folders within a Tree without Parents or Subfolders with a Regexp

Post by Dustydog » 23 Dec 2016 09:42

[If there's a better way of doing this (highend) feel free to mention it. :wink: ]

I was in the position the other day of wanting to remove some intervening folders:

C:\Some Parent Folder\Junk Folders with Child Folders\I Wanted to Get These Folders\Whatever.

The only way I could find to do this was enter a standard search, quoted only, check include subfolders, check path, attributes = Directory.

In the name box, quoted: "C:\Some Parent Folder\*\*\" <- (I couldn't find a way of doing that with a regex search, though it's a trivial one in, say, "Everything.")

This gives me a search results of all the "I Wanted to Get These Folders" without showing the parents. I could then select them from the search result and operate on them (it was a regex to file them differently based on part of those folder names). Then I went back and deleted the newly empty parent folders showing - thank you again Don - the contents of the folders being empty with no more subfolders or files - or in my case a few that didn't match the regex that I had to tweak a bit more. I ended up with some nicely combined files into new, better, parent folders.

I know this may be a somewhat odd situation, but it was difficult enough (for me) to figure out, and useful enough, that I thought I'd share it. Having it in quotes only was a bit long in the finding.
Last edited by Dustydog on 03 Feb 2017 23:29, edited 1 time in total.

highend
Posts: 9101
Joined: 06 Feb 2011 00:33

Re: How to Show Folders within Folders without Parents in Search

Post by highend » 24 Dec 2016 13:38

I probably wouldn't do it this way (too much repetition and hard to remember)
but with a script that either loads a search template (which is rewritten to use
the current path and a named search that get's the folder <x> levels deep depending
on user input) or uses quicksearch to get all folders recursively, filters it (again: <x>
levels deep) and put the results into a paperfolder...
One of my scripts helped you out? Please donate via Paypal or paypal_donate (at) stdmail (dot) de

Dustydog
Posts: 315
Joined: 13 Jun 2016 04:19

Re: How to Show Folders within Folders without Parents in Search

Post by Dustydog » 03 Feb 2017 23:19

highend wrote:I probably wouldn't do it this way (too much repetition and hard to remember)
but with a script that either loads a search template (which is rewritten to use
the current path and a named search that get's the folder <x> levels deep depending
on user input) or uses quicksearch to get all folders recursively, filters it (again: <x>
levels deep) and put the results into a paperfolder...
Thank you, sincerely, for commenting. I'd prefer not to use a paper folder unless I have to as there's rather a lot of data. I appreciate your brainstorming several options.

But I really wanted my regex, which I did in fact flub. Of course - the "$" is absolutely necessary.

I finally got it! This one's useful:

No Quotes, requires subfolders, paths, attribute=directory. You need to be on the drive involved - even if the location is empty - so perhaps have "Auto Sync" on as well.

G:\\Test(\\([^\\]+)){3}$

Acting on a folder structure like:
G:\Test\Test One Down\2 Down\3 Down\4 Down\New Text File 1.txt
G:\Test\Test One Down\Two Down\Three Down\Four Down\New Text File Two.txt

It provides (with 3, can change the number and go up or down the folder structure) these folders as results:
"3 Down"
"Three Down"

No folders above or below - which is just what I wanted.

Obviously this is quite powerful as one could tweak the regex however one wished - just pull a group out of the repeating group as needed and customize. Or simply use it to remove intervening folders and operate on the result - which was my original goal.

***

I couldn't figure out, using the standard interface in Find, how I could modify this to work on the current folder, so the base working folder has to be copy-pasted into the regex. I'll treat this as a scripting challenge :) Somehow I need to fill this into the "Name" box, which doesn't apparently support variables directly.

highend
Posts: 9101
Joined: 06 Feb 2011 00:33

Re: How to Show Folders within Folders without Parents in Search

Post by highend » 03 Feb 2017 23:30

Like I said, load a search template that you premanipulate (does that word even exist? :D)
And the scripting approach makes it 10 times less hard to remember because you could
just ask for how many levels deep (which then replaces your "3" in your example)
One of my scripts helped you out? Please donate via Paypal or paypal_donate (at) stdmail (dot) de

highend
Posts: 9101
Joined: 06 Feb 2011 00:33

Re: How to Show Folders within a Tree without Parents or Subfolders with a Regexp

Post by highend » 04 Feb 2017 02:01

Just to show you how easy and powerful this actually is...

Nothing to remember
Just input a level or a range (nice if you want to get something between 3 and 6 subfolder levels deep)
Ranges can be formed with either an "," or "-"
2,5; 1-4; etc. are valid inputs
Executable with a keyboard shortcut / catalog / udc / button, whatever
Done...

Code: Select all

    $searchTemplate = <<<>>>
[Find]
Version=3
Mode=2
FullPath=1
Case=0
InclSubs=1
Inverted=0
Fuzzy=0
FollowFolderLinks=0
SelectedLocations=0
WholeWords=0
AutoSync=0
IgnoreDiacritics=0
FuzzIndex=0
TypeFilter=0
AttrFindCheck=16
AttrFindNotCheck=0
Mind0=1
Mind3=1

[Named]
Named=

[LookIn]
LookIn="<curpath>"
>>>;

    $levels = input("Enter level...", "<x> subfolders from here", 3);
    $range  = regexreplace($levels, "(\d+)(?:-|,)(\d+)?", "$1,$2");
    $named  = replace(<curpath>, "\", "\\") . "(\\([^\\]+)){$range}$";
    $searchTemplate = replace($searchTemplate, "Named=", "Named=" . quote($named));
    $templateFile = "<xydata>\FindTemplates\subfolderlevels.ini";
    writefile($templateFile, $searchTemplate);
    loadsearch "subfolderlevels", "rl";
    delete 1, 0, $templateFile;
One of my scripts helped you out? Please donate via Paypal or paypal_donate (at) stdmail (dot) de

Dustydog
Posts: 315
Joined: 13 Jun 2016 04:19

Re: How to Show Folders within a Tree without Parents or Subfolders with a Regexp

Post by Dustydog » 10 Feb 2017 01:45

highend wrote:Just to show you how easy and powerful this actually is...

Nothing to remember
Just input a level or a range (nice if you want to get something between 3 and 6 subfolder levels deep)
Ranges can be formed with either an "," or "-"
2,5; 1-4; etc. are valid inputs
Executable with a keyboard shortcut / catalog / udc / button, whatever
Done...
Thank you, Sir! I appreciate your taking the time on that script - some of what it does is above my head at the moment, but won't be for long. Very useful for me to study (and use). I admire your skill and knowledge...hope I'll get there eventually, certainly going to keep at it. Thank you, again, for your help.

[BTW, I think this is an appropriate icon for your script: http://www.iconarchive.com/show/i-icons ... -icon.html]

Dustydog
Posts: 315
Joined: 13 Jun 2016 04:19

Re: How to Show Folders within a Tree without Parents or Subfolders with a Regexp

Post by Dustydog » 12 Feb 2017 00:23

There's an interesting limitation to this, but not to my original quoted solution that doesn't use a regex ("C:\User\Me\That Folder\*\*" /maxdepth=2, etc.).

One can't use it on one's users folders - at least one's Downloads folder - though it works everywhere else.

Highend - do you know why this is the case in detail? I know the folders have extra programming attached and don't follow the usual rules. [I do have all follow links settings active, if that could make a difference.]

Interestingly enough, it WILL work on the user folders (at least Downloads) over an SMB share - go figure. (I am aware that links (junctions and symlinks) act somewhat differently over network shares. And I assume some OS code...interference in this case...is unlikely to kick in over the share. Really don't know the details of why this is acting odd through XY, though. My user folders aren't redirected to anywhere unusual.)

Of course, a very simple solution is to copy the whole thing to somewhere else and use the regex solutions. And Downloads isn't a typical location - though useful when it is.

Still wish I knew the why of it, though. As I think about it, I believe I struggled with the regex while using a user folder, then got it when I wasn't - which makes sense, obviously, given the behavior above.

[Does work in "Everything," so wondering if it's an XY quirk?]

highend
Posts: 9101
Joined: 06 Feb 2011 00:33

Re: How to Show Folders within a Tree without Parents or Subfolders with a Regexp

Post by highend » 14 Feb 2017 15:48

Haven't tried this. My folders are relocated anyway so the only good way to test it: A VM.
Provide an exact setup for this, please (path structure, regex used, etc.)
One of my scripts helped you out? Please donate via Paypal or paypal_donate (at) stdmail (dot) de

Dustydog
Posts: 315
Joined: 13 Jun 2016 04:19

Re: How to Show Folders within a Tree without Parents or Subfolders with a Regexp

Post by Dustydog » 11 Apr 2017 09:02

Here's a small update of highend's excellent script for regex selecting a folder out of a hierarchy. My part in it is just unattractive regex grunt work, but it does make it work without having to hand escape characters in the resulting regex in the Find box.

Code: Select all

$searchTemplate = <<<>>>
[Find]
Version=3
Mode=2
FullPath=1
Case=0
InclSubs=1
Inverted=0
Fuzzy=0
FollowFolderLinks=0
SelectedLocations=0
WholeWords=0
AutoSync=1
IgnoreDiacritics=0
FuzzIndex=0
TypeFilter=0
AttrFindCheck=16
AttrFindNotCheck=0
Mind0=1
Mind3=1

[Named]
Named=

[LookIn]
LookIn="<curpath>"
>>>;

    $levels = input("Enter level...", "<x> subfolders from here", 3);
    $range  = regexreplace($levels, "(\d+)(?:-|,)(\d+)?", "$1,$2");
    $named  = replace(<curpath>, "\", "\\") . "(\\([^\\]+)){$range}$";

    //The regex is simply an alternation that replaces each symbol with itself escaped
    //Unless it's followed by a pattern used in the main regex through  a long series of negative lookahead alternations.
    $named  = regexreplace($named, "(?!(?:\(\\|\)\W|\(\[\^|\+\)\))|\[\^\\|\^\\\\|\{\d\}|\$$)(\(|\)|\[|\+|\^|\{|\$)", "\$1");
    $named  = """$named""";

    $searchTemplate = replace($searchTemplate, "Named=", "Named=" . quote($named));
    $templateFile = "<xydata>\FindTemplates\subfolderlevels.ini";
    writefile($templateFile, $searchTemplate);
    loadsearch "subfolderlevels", "rl";
    delete 1, 0, $templateFile;

/*Version 1.1
Escapes legal path characters that are used in the regex without escaping them as control characters: ( ) [ + ^ { $
Changed AutoSync to Active.
Put entire main regex inside quotes, which is apparently needed for some paths.

The main script is by highend.
*/
Has been tested against user folders and folders containing a variety of control characters.

Thank you again, highend, for the time you put into this - it's a useful script for me.

highend
Posts: 9101
Joined: 06 Feb 2011 00:33

Re: How to Show Folders within a Tree without Parents or Subfolders with a Regexp

Post by highend » 11 Apr 2017 09:15

I'm getting blind looking at that regex :D, so...

The only thing you want to do is escaping meta chars in a string?
(This is a version for strings, not only files / folders)

Code: Select all

$string = regexreplace($string, "([\\^$.+*|?(){\[])", "\$1");
One of my scripts helped you out? Please donate via Paypal or paypal_donate (at) stdmail (dot) de

Dustydog
Posts: 315
Joined: 13 Jun 2016 04:19

Re: How to Show Folders within a Tree without Parents or Subfolders with a Regexp

Post by Dustydog » 14 Apr 2017 03:13

highend wrote:I'm getting blind looking at that regex :D, so...

The only thing you want to do is escaping meta chars in a string?
(This is a version for strings, not only files / folders)

Code: Select all

$string = regexreplace($string, "([\\^$.+*|?(){\[])", "\$1");
Lol, yes, that'd do it.

Thing was, it kind of crept up on me. I started by just escaping a parenthesis - I use them at the beginning of folders to make them sort top and look obvious. Then realized I've got a few with brackets. Then braces. Then I just went what the heck and finished.

And yes, as a one liner, it looks awful.

Should've used a custom character class in the beginning instead of an alternation and applied it before the regex got appended.

(At least it works :oops: )

Dustydog
Posts: 315
Joined: 13 Jun 2016 04:19

Re: How to Show Folders within a Tree without Parents or Subfolders with a Regexp

Post by Dustydog » 03 May 2017 20:39

Finally got around to this, which is a finally a solid script (that I personally use frequently).

One use is quickly selecting folders part way down a hierarchy to remove intervening folders that are (no longer) desired. An example would be refiling music files if you've used a deep hierarchy system and want to change it - or simply copy several out to transcode and move to a player. Another would be if you have multiple files with useless zipped folder names, extract them all, then only want only the contents, leaving empty folders. If you remove the attribute=directory after the script has left the Find box filled out for you, it can be handy to see all the contents of all folders at a given level, folder and/or file. The thing this is closest to natively is, perhaps, doing a branch view, folders only. This, however, makes the folders you're actually interested in easy to select and move without intervening parents, or things like separate CD1 CD2 folders popping up underneath what you're interested in.

There's a few too many comments in the script, but they help keep me oriented after some time has gone by so I left them.

All hail highend for the main temporary search template script and great advice. I have a tendency to do this kind of thing interactively rather than with a script, which is neither elegant nor as quick. Thanks to Don, however, it is reasonably quick to load a search template and then tweak it, but this is certainly quicker. It also leaves the entry in the Find box afterwards for hand tweaking if desired, as I mentioned - which is particularly helpful if you use special characters in your folder names that conflict with a regular expression and need to be escaped. The main regular expression used, and the regular expression that escapes regex characters from a pathname, are both perhaps worth reusing in your own scripts, or at least are worth glancing at.

Code: Select all

//Version 1.2

//Usage: Find all folders a given distance down the heirarchy from <curfolder>, but no deeper, by entering range 1[- or ,#] using a regex using a self-removing Search Template.


/*
Examples, Notes, and FYIs:

If one had only this path: E:\Here I Am\These Are Garbage\This is What I Want\This is Too Deep\Etc\Etc.txt

If you're in the folder, "Here I Am" and select "2" in the pop-up dialogue, the default,
it will show the folder "This is What I Want" without subfolders or parents,
    using the regex: "E:\\Here I Am(\\([^\\]+)){2}$"  (FYI: "$" is required.)
  Enter "3" and it will show "This is Too Low" instead.
  Enter "2-3" or "2,3" and it will show "This is What I Want" along with "This is Too Low".
  
FYI: You can break out the group (\\([^\\]+)) for a given folder level(s) if you want to further restrict intervening folders using a regex, 
FYI: From "Here I Am" with a normal search, using /maxdepth=1 would give you both "These Are Garbage" and "This is What I Want". There is no /mindepth= in XY.
FYI: One can accomplish almost the same thing without a regex by using the following with a Standard search:
  "<curpath>\*\*" /maxdepth=1     <-Under "Name" in the Find Box, Quotes required.
    which returns the folder "This is What I Want"
  /maxdepth=2 would return "This is Too Deep" as well.
    Also select: Path, Include subfolders, Auto sync, Attributes, and Attributes=Directory.
*/

$searchTemplate = <<<>>>
[Find]
Version=3
Mode=2
FullPath=1
Case=0
InclSubs=1
Inverted=0
Fuzzy=0
FollowFolderLinks=0
SelectedLocations=0
WholeWords=0
AutoSync=1
IgnoreDiacritics=0
FuzzIndex=0
TypeFilter=0
AttrFindCheck=16
AttrFindNotCheck=0
Mind0=1
Mind3=1

[Named]
Named=

[LookIn]
LookIn="<curpath>"
>>>;
//Input
    $levels   = input("Enter level...", "<x>[-<y>] subfolders from here", 2); //Depth=2 default.
    $range    = regexreplace($levels, "(\d+)(?:-|,)(\d+)?", "$1,$2");         //Lets x; x,y; or x-y work as input.
//Prepare Regex into "$named" for Name in Search Template Find Box.
    $regexesc = regexreplace(<curpath>, "([][{}()*+?.\\^$|])", "\$1");        //Escape the path for regex use.
    $named    = $regexesc . "(\\([^\\]+)){$range}$";                          //Append main regex for folder depth.
    $named    = """$named""";                                                 //Put the whole thing in quotes.
//Search Template
    $searchTemplate = replace($searchTemplate, "Named=", "Named=" . quote($named));
    $templateFile = "<xydata>\FindTemplates\subfolderlevels.ini";
    writefile($templateFile, $searchTemplate);
    loadsearch "subfolderlevels", "rl";
    delete 1, 0, $templateFile;

/*For Version 1.2:
-Commented.
-Escapes regex control characters in starting path by individually replacing 
       all members of a regex character class containing all regex control characters
       with each match slash-escaped: \$1. 
   For reusability, the class includes characters that it will never find
       (|, *, etc.) as they're illegal in a windows path anyway.
   FYI: XY doesn't support $0.
-Puts the whole thing in quotes as some paths require it.
-Changed default depth to "2", as its primary use (for me at least) is 
   to bypass intervening garbage folders of varying names.
-Disposes of painful regex in v1.1 which needed ")" escaped anyway.

Note: It's useful to reuse the filled-in Find Box as needed, 
        such as changing attrib: folder or tweaking the regex to be more exclusive.

Started and finished by Dustydog.
The main search template script is by highend.
Most of the good advice is from highend.
*/

pdupreez
Posts: 19
Joined: 15 Aug 2018 11:40

Re: How to Show Folders within a Tree without Parents or Subfolders with a Regexp

Post by pdupreez » 15 Aug 2018 11:47

I have been using XYplorer for many years, obviously like an newbie, but today suddenly needed to find a solution for a problem and finding myself here after a round of Google. The scripts is useful, but not what I need exactly, but given my absolute lack of programming skills I was hoping for some help here.

I need to obtain a list of folders which have no subdirectories, only files from the current folder

i.e if I have

Drive:/Current Dir/Folder A/Subfolder 1
Drive:/Current Dir/Folder B/Subfolder 1
Drive:/Current Dir/Folder C/any files

I only want to see a "list" with Drive:/Current Dir/Folder C/any files and obviously every other one in CurrentDir that has the same lack of subdirectories


Any help, much appreciated

highend
Posts: 9101
Joined: 06 Feb 2011 00:33

Re: How to Show Folders within a Tree without Parents or Subfolders with a Regexp

Post by highend » 15 Aug 2018 11:56

That's incredible easy...

Code: Select all

goto <curpath> . "\? /f";
One of my scripts helped you out? Please donate via Paypal or paypal_donate (at) stdmail (dot) de

pdupreez
Posts: 19
Joined: 15 Aug 2018 11:40

Re: How to Show Folders within a Tree without Parents or Subfolders with a Regexp

Post by pdupreez » 15 Aug 2018 12:05

highend wrote:That's incredible easy...

Code: Select all

goto <curpath> . "\? /f";
Thank you so much for your prompt reply, but I think I have not explained well enough. I only need the folders/paths of the folders without subdirectories, not the files itself in them. I am better (debatable) explaining by example:

Drive:/Current Dir/Folder A/Subfolder 1
Drive:/Current Dir/Folder B/Subfolder 1
Drive:/Current Dir/Folder C/Only Files
Drive:/Current Dir/Folder D/Only Files
Drive:/Current Dir/Folder E/Subfolder 1
Drive:/Current Dir/Folder F/Only Files

I only want to see a "list" with folders without any subfolders, ie:

Drive:/Current Dir/Folder C
Drive:/Current Dir/Folder D
Drive:/Current Dir/Folder F

Post Reply