Page 1 of 1

listfolder filter

Posted: 22 Nov 2014 20:58
by klownboy
Hi, I'm generating a listing of image files (e.g., jpg, bmp, png, etc.) within a folder. In the end, I only want the filenames (no paths and no folders) so SC listfolder is ideal for this. The image list is used in command line for ImageMagick and it needs the list with each filename 'single' quoted separated by a "<crlf>". Apparently though, SC listfolder only accepts one filter (e.g., *.jpg) is that correct? The only examples I see both on the forum and in the help file are using a single filter and in experimenting I've only been able to get one to work. I have done what I have to do using SC folderreport and formatlist to filter out only the image type files and then obtain the filenames only with getpathcomponent in a foreach loop. Is that the only way achieve what I want to accomplish. Does any body know a better way?

Don any chance that you could make SC listfolder accept multiple filters?

Thanks,
Ken

Re: listfolder filter

Posted: 22 Nov 2014 21:14
by highend
At least getting rid of folder paths can be done much faster by using a regexreplace() instead of a loop.

E.g.:

Code: Select all

    $test = <<<>>>
'D:\Users\Highend\Downloads\Explorer - Sidebar Einträge.txt'
'D:\Users\Highend\Downloads\finnix-110.iso'
'D:\Users\Highend\Downloads\GPT Partition setup.txt'
'D:\Users\Highend\Downloads\HERE_beta_220.apk'
'D:\Users\Highend\Downloads\IFL.iso'
'D:\Users\Highend\Downloads\Kindersicherungen [Android + iOS].png'
'D:\Users\Highend\Downloads\Kindersicherungen [Windows].png'
>>>;

    $test = regexreplace($test, "^(')(.*\\)(.*?$)", "$1$3");
    text $test;
A slightly different way:

Code: Select all

    $test = folderreport("files:{name}", "r", "D:\Users\Highend\Downloads", , , "<crlf>");
    $test = formatlist($test, "f", "<crlf>", "!*.pdf<crlf>*.txt");
    $test = regexreplace($test, "^(.*?)$(\r?\n|$)", "'$1'$2");
    text $test;
I haven't tested which one is faster :)

Re: listfolder filter

Posted: 22 Nov 2014 23:29
by klownboy
Hi highend, thanks very much for the regex methods/examples. Using your first regex method (regexreplace($test, "^(')(.*\\)(.*?$)", "$1$3");), how would the regex change if, unlike what I said above the list wasn't single quoted (yet), I used a standard folderreport and formatlist with an "|" or an "<crlf>" separator like this...

Code: Select all

 $images = formatlist(folderreport("files", "r", "<curpath>", , , "|"), "f", "|", "*.jpeg|*.jpg|*.bmp|*.png");
   $image_list = ""; $i = "1";
   foreach($item, $images, "|") {
		if ($item == "") {continue;}
      $name = getpathcomponent($item, "file");
      $image_list = $image_list . "'$name'" . "<crlf>"; $i++;
   }
I was using a foreach loop as I said, but it was actually doing 3 functions; 1) stripping the path from the filename, 2) obtaining the count of the images, and 3) placing single quotes around each filename in the list. I suppose what I'm asking too is, can I achieve the single quoting some how within the regex or the formatlist? I can use SC gettoken now for the count. In the end, I need a list similar to what you have for your $test above, but with only the filenames (no paths). The above works fine, but I'm always looking to get smarter. :D
Thanks,
Ken

Re: listfolder filter

Posted: 23 Nov 2014 00:34
by highend
The (probably) fastest way to replace your foreach loop could be:

Code: Select all

text regexreplace(formatlist(folderreport("files:{name}", "r", "<curpath>", , , "<crlf>"), "f", "<crlf>", "*.jpeg<crlf>*.jpg<crlf>*.bmp<crlf>*.png"), "^(.*?)$(\r?\n|$)", "'$1'$2");
I guess it doesn't matter much if we use a folderreport with the files: template where we put the ' around {name} and use a slightly different regex to strip the paths or if we add (as in my example) them in the replacement "'$1'$2".

It's easier to do everything with "<crlf>" right from the beginning if we want an output that is formatted this way. Although it looks weird when the pattern for the file extension is separated by <crlf> instead of a bar ("|").
how would the regex change if, unlike what I said above the list wasn't single quoted (yet), I used a standard folderreport and formatlist with an "|" or an "<crlf>"
For <crlf>:

Code: Select all

$test = regexreplace($test, "^(.*\\)(.*?$)", "$2");
For |:

Code: Select all

$test = regexreplace($test, "(?:^|\|)(.*?\\)([^\\]+)(?=\||$)", "$2<crlf>");
This is a bit of an advanced regex^^

(?:^|\|) = Don't put the beginning of the line or a bar into a backreference group
(.*?\\) = Lazy match of everything up to a backslash (first backreference)
([^\\]+) = Everything that doesn't contain a backslash (second backreference -> hence the $2 in the replacement code)
(?=\||$) = Do not capture an ending bar or the end of the line

$2<crlf> = Give back the second backreference group and put a <crlf> behind it

This would transform this:
D:\Users\Highend\Downloads\Explorer - Sidebar Einträge.txt|D:\Users\Highend\Downloads\finnix-110.iso|D:\Users\Highend\Downloads\GPT Partition setup.txt|D:\Users\Highend\Downloads\HERE_beta_220.apk|D:\Users\Highend\Downloads\IFL.iso|D:\Users\Highend\Downloads\Kindersicherungen [Android + iOS].png|D:\Users\Highend\Downloads\Kindersicherungen [Windows].png
into this:
Explorer - Sidebar Einträge.txt
finnix-110.iso
GPT Partition setup.txt
HERE_beta_220.apk
IFL.iso
Kindersicherungen [Android + iOS].png
Kindersicherungen [Windows].png

Re: listfolder filter

Posted: 23 Nov 2014 01:13
by klownboy
Wow, thanks highend. I have some studying and testing to do. If I didn't use template {name} and wanted to achieve the single quoted list, it looks like putting the single quote around the '$2' does the single quoting for the listing when doing in two steps....just testing. I'm not sure which way I'll go yet.

Code: Select all

	 $test = formatlist(folderreport("files", "r", "<curpath>", , , "<crlf>"), "f", "<crlf>", "*.jpeg<crlf>*.jpg<crlf>*.bmp<crlf>*.png");  
	 $test = regexreplace($test, "^(.*\\)(.*?$)", "'$2'"); text $test;
In my past experience using a template with folderereort tended to be slower but maybe not in this case especially since you're accomplishing everything at once.
Thanks so much,
Ken

Re: listfolder filter

Posted: 23 Nov 2014 12:27
by klownboy
Hi highend, reporting back after performing some time test using the 3 methods performing as stated above:

Code: Select all

               Time in mSecs                                             Test folder size No of Images
                                                                              189   220      250      579 
  formatlist & folderreport [using template {name}] & regex all in on line    109    31      40       343
  formatlist & folderreport and a foreach loop                                94     77      93       220 
  formatlist & folderreport & regex in 2 step/lines                           16     13      16        31
Not scientific by any stretch of the imagination, but it does reflect that the two step [formatlist & folderreport & regex in 2 step/lines] is faster than the foreach or the folderreport using template {name}. In some runs the foreach loop was actually faster than folderreport using the template.
Thanks again highend.
Ken

Re: listfolder filter

Posted: 23 Nov 2014 12:41
by highend
So after all:

- Avoid templates in folderreport()
- Use regexreplace (to remove paths & insert e.g. leading / trailing characters)

is the fastest way, right?

Re: listfolder filter

Posted: 23 Nov 2014 13:51
by klownboy
Yes, I'd say you are right. Back awhile ago I ran some other tests using a more complex template with folderreport and it ran slower as well. It is unfortunate because it is extremely powerful. Thanks again.