Sunday, July 22, 2018

#1 2014-03-08 12:06:51 pm

partron22
Member
Registered: 2011-03-18
Posts: 86

Unexpected Wrinkle Using Shell Script to Get Filenames

I've been using do shell script "ls -p " &... for a long time now, and finally noticed it doesn't give the result expected when a filename includes a slash character.
If a folder contains for example, a file named "10/23/14 Goldfish1.jpg", ls, in Terminal or AppleScript Editor, will return it as "10:23:14 Goldfish1.jpg".

As far as Finder is concerned, that's an illegal filename for a nonexistent file.
It'll cause an error if you Tell the Finder to do something with it.

The quick and easy fix is to use sed to convert all those errant colons back into slashes.
Here's the code:

Applescript:

-- BP 2014
-- ls sed Get names of files in folder
-- Fix filenames that include "/"
-- ls converts / in filenames to :
-- A file named "10/23/14 Goldfish1.jpg" thus becomes "10:23:14 Goldfish1.jpg" which will choke the Finder
-- if you tell it to do something with the file.
-- Let's also use the ls -p flag to easily Filter folders from the directory listing

set fldrpath to (choose folder) as text
set fldrpath to (text 1 through ((length of fldrpath) - 1) of fldrpath) as text -- strip off the ending colon
set pospath to POSIX path of fldrpath -- convert to a UNIX friendly form
set pospath to quoted form of pospath

set namstr to do shell script "ls -p " & pospath -- get names of files in the folder The -p option flags folders by adding a trailing/

-- We have a string (namstr) with all the filenames in it, but Unix ls has helpfully replaced any '/'s in those file names with ':'s, which will choke the Finder, so I need to set the :'s back to /'s before continuing.
-- This is a job for sed.
-- sed pattern needs some nudging to make it through Applescript's parsing
-- This works in Terminal: x="AB:DEF:mugwart" | x=`echo $x | sed 's/:/\//g'` | echo $x
----> AB/DEF/mugwart
-- Applescript shell script needs DOUBLE backslashses and quoted form to make it intact through the parser:
set SRpattern to quoted form of "s/:/\\//g" -- colon to slash -- Note Quoted form and DOUBLE backslash before the / character
set namstr to do shell script "echo " & quoted form of namstr & " | sed " & SRpattern
-- All the colons are now slashes again, and I can move on.

set oldtid to AppleScript's text item delimiters -- Convert the namstr text to a list
set AppleScript's text item delimiters to "\r"
set dirlst to every text item of namstr
set AppleScript's text item delimiters to oldtid

-- Folders, Apps and the like will appear in dirlst, but are easily filtered out when using ls -p because they all end with "/"
-- Files without extensions, whose names end in a "/" will be filtered out too here.
--return dirlst

set filnamlst to {}
set directoryflag to "/" -- ls -p flags folders, Apps etc with this
repeat with z in dirlst
   if the last text item of z is not directoryflag then set end of filnamlst to z as text
end repeat

-- Now the Finder won't choke when I tell it to do something with a file named "10:23:14 Goldfish1.jpg" or similar.

return filnamlst

I never noticed this problem before because I almost never put slashes in filenames. It's probably caused a few crashes for me, some people would likely be harder hit.

Last edited by partron22 (2014-03-08 12:17:54 pm)


Filed under: sed, shell, ls

Offline

 

#2 2014-03-08 08:12:12 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5410

Re: Unexpected Wrinkle Using Shell Script to Get Filenames

Using sed is probably a bit of overkill -- tr will do what you want:

Applescript:

set namstr to do shell script "ls -p " & posPath & " | tr / :"

Last edited by Shane Stanley (2014-03-08 08:12:27 pm)


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#3 2014-03-08 09:31:53 pm

partron22
Member
Registered: 2011-03-18
Posts: 86

Re: Unexpected Wrinkle Using Shell Script to Get Filenames

Shane Stanley wrote:

tr will do what you want"


tr / : is a lot more readable than the sed string.

Thanks!

Last edited by partron22 (2014-03-08 09:33:31 pm)

Offline

 

#4 2014-03-09 04:01:23 am

Nigel Garvey
Moderator
From:: Warwickshire, England
Registered: 2002-11-20
Posts: 4604

Re: Unexpected Wrinkle Using Shell Script to Get Filenames

Mind you, for this job, sed could also filter out the slash-terminated folder names:

Applescript:

set pospath to POSIX path of (choose folder)
set filnamlst to paragraphs of (do shell script ("ls -p " & (quoted form of pospath) & " | sed -n '/\\/$/ !{ s/:/\\//g ; p ; }'"))

By using a different delimiter with sed's 's' function, you can avoid having to escape the replacement slash. For example, with bars: "sed 's|:|/|g'". But since the address parameter here has to have slashes anyway, I've used slashes with 's' too for consistency.


NG

Offline

 

#5 2014-03-09 11:52:32 am

partron22
Member
Registered: 2011-03-18
Posts: 86

Re: Unexpected Wrinkle Using Shell Script to Get Filenames

Nigel Garvey wrote:

Mind you, for this job, sed could also filter out the slash-terminated folder names:

Applescript:

set pospath to POSIX path of (choose folder)
set filnamlst to paragraphs of (do shell script ("ls -p " & (quoted form of pospath) & " | sed -n '/\\/$/ !{ s/:/\\//g ; p ; }'"))


Well that certainly kills a few lines of code!
Three or four birds with one stone, not terribly readable, but it does kill one of those ugly and slow "repeat with x in y" loops.
Wonderful, thanks.

Last edited by partron22 (2014-03-09 11:54:07 am)

Offline

 

#6 2014-03-10 03:57:35 am

Nigel Garvey
Moderator
From:: Warwickshire, England
Registered: 2002-11-20
Posts: 4604

Re: Unexpected Wrinkle Using Shell Script to Get Filenames

partron22 wrote:

… not terribly readable …


No worse than ASObjC.  wink

Here's the same code with added linefeeds, indents, comments, and backslash avoidance:

Applescript:

set pospath to POSIX path of (choose folder)
set filnamlst to paragraphs of ¬
   (do shell script ("
       # Get the names (one per line) of the items in the folder, with slashes appended to any folder or bundle names.
       ls -p "
& (quoted form of pospath) & " |
       # Edit the lines, outputting only where specified.
       sed -n '
           /[/]$/ !{        # Where a line does not end with a slash …
               s|:|/|g ;    # … substitute slashes for colons …
               p ;        # … and output.
           }
       '
   "
))


NG

Offline

 

#7 2014-03-10 05:26:57 am

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5410

Re: Unexpected Wrinkle Using Shell Script to Get Filenames

Nigel Garvey wrote:

No worse than ASObjC.  wink


I'll take verbose over cryptic any day tongue


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#8 2014-03-10 12:43:38 pm

McUsrII
Member
Registered: 2012-11-21
Posts: 3046
Website

Re: Unexpected Wrinkle Using Shell Script to Get Filenames

Shane Stanley wrote:
Nigel Garvey wrote:

No worse than ASObjC.  wink


I'll take verbose over cryptic any day tongue


Beauty is in the eye of the beholder. big_smile

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)