Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

A Perl script to manage file types and creators UNIX

WHAT
A perl script to (batch) view and change the type and creator of files from the terminal. You'll need the DevTools installed, as the script uses SetFile and GetFile to work.

WHY
To make open ./file work from the terminal and override the infuriating default extension-application correspondence. Please feel free to improve the script---I'm sure there's lots of room for improvement.

USE
Paste it into a file and save it (with UNIX line endings) somewhere on your PATH. I call it tc.

To view types & creators:
tc *.txt

To set types
tc -t TEXT *.txt

To set creators
tc -c ALFA *.txt

You can set types and creators simultaneously in the obvious way. Read the rest of the hint for the script...

THE SCRIPT


#!/usr/bin/perl

@files = ();

$type_ = 0;
$creator_ = 0;

$i=0;
while( $i <= $#ARGV ) {
  if( $ARGV[$i] eq "-t" ) {
    $type = $ARGV[$i+1];
    $type_ = 1;
    print "   Change type to \"$type\"\n";
    if( length($type) != 4 ) {
      print "Type \"$type\" does not have length 4. Try using quotes if you need spaces.\n";
      $i = $#ARGV;
    }
    $i = $i+2;
  }
  elsif ( $ARGV[$i] eq "-c" ) {
    $creator = $ARGV[$i+1];
    $creator_ = 1;
    print "Change creator to \"$creator\"\n";
    if( length($type) != 4 ) {
      print "Creator \"$creator\" does not have length 4. Try using quotes if you need spaces.\n";
      $i = $#ARGV;
    }
    $i = $i+2;
  }
  else {
    push(@files, $ARGV[$i]);
    $i++;
  }
}

foreach $file (@files) {
  if( $type_ == 1 ) {
    `SetFile -t '$type' '$file'`;
  }
  if( $creator_ == 1 ) {
    `SetFile -c '$creator' '$file'`;
  }
  
  $newtype = `GetFileInfo -t '$file'`;
  chomp($newtype);
  $newcreator = `GetFileInfo -c '$file'`;
  chomp($newcreator);

  print "$newtype   $newcreator  $file\n";

}

if( $i == 0 ) {
  print "  usage: tc [-t TYPE] [-c TYPE] filenames\n";
  print "  if type and creator are present then they will be set for the files\n"; 
  print "  otherwise the type and creator of the files are displayed\n"; 

}

QUESTION
BTW: Does anybody know how to change the default extension-application correspondence?

    •    
  • Currently 1.00 / 5
  • 1
  • 2
  • 3
  • 4
  • 5
  (1 vote cast)
 
[9,487 views]  

A Perl script to manage file types and creators | 17 comments | Create New Account
Click here to return to the 'A Perl script to manage file types and creators' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
A Perl script to manage file types and creators
Authored by: JohnnyMnemonic on Dec 05, '03 11:00:21AM
You can change the default extension application correspondence from the Get Info window, of course. (Select "Open With", pull down to your preference, then "change all" to set a new default.)

What I suspect that you're asking, though, is how can you do this from the command line? That's a good question. I suspect that it lives in a user preference someplace, as it doesn't require an admin action to perform (I don't believe) but I'm not sure if the changes to default apply system-wide or just to the user. The bigger question--if this is indeed a preference, is it kept in XML in a .plist someplace, or is it in Apple Proprietary code?

[ Reply to This | # ]
default extension application
Authored by: taran on Dec 05, '03 01:44:51PM
The bigger question--if this is indeed a preference, is it kept in XML in a .plist someplace, or is it in Apple Proprietary code?
This is stored in, e.g., /Applications/TextEdit.app/Contents/Info.plist. Open this file in your favorite text editor and search for <key>CFBundleTypeExtensions</key> (one per extension) or, e.g., <string>txt</string>.

[ Reply to This | # ]
default extension application
Authored by: hamarkus on Dec 05, '03 08:08:56PM

Looking at that file on my computer it seems that only the file types which are to be opened with TextEdit are stored there. And checking the corresponding file with Acrobat 6.0.1.app shows that the .pdf extension is listed there.

But some carbon applications are not bundles (e.g. Acrobat 5, Word X), so where is it stored for the them?
I have both Acrobat 5 and 6 installed. I set .pdfs to be opened with Acrobat 6, via the Get Info command and apply to all. This did not stick all of the times, with old .pdfs still being opened in Acrobat 5.



[ Reply to This | # ]
also, refer to prior hint here ...
Authored by: blakers on Dec 05, '03 01:00:42PM

hi all,

for those interested, there's also an available set of utils, "osxutils", mentioned in a prior hint ...

"Install a useful set of OS X specific command line apps"
http://www.macosxhints.com/article.php?story=20030529165622989&query=setfctypes

... which includes, amont others, "setfctypes" for the same purpose.

cheers,

richard



[ Reply to This | # ]
A Perl script to manage file types and creators
Authored by: dierauer on Dec 05, '03 01:18:04PM
Here's my version of this script, made more readable by using the standard perl module Getopt::Std to process command-line switches.

#!/usr/bin/perl
use strict; #-- strict and warnings are always a good idea!
use warnings;
use Getopt::Std; #-- standard perl module

#-- written by David Dierauer (dierauer at NOSPAMvoyager.net) 05-DEC-2003
#-- based on the 'tc' perl script by 'anonymous' posted to macosxhints

my $usage = "usage: $0 [-t TYPE][-c creator] filenames\n"
   . "\tif type and creator are present then they will be set for the files;\n"
   . "\totherwise the type and creator of the files are displayed\n"; 

our ( $opt_c, $opt_t );
getopts( 'c:t:' );

foreach my $opt ( $opt_t, $opt_c )
{
   if ( $opt and length($opt) != 4 )
   {
      die "'$opt' does not have length 4; try using quotes if you need spaces.\n";
   }
}
my @files = @ARGV;
@files or die $usage;

my $devtools = '/Developer/Tools';
foreach my $file ( @files )
{
   `$devtools/SetFile -t '$opt_t' '$file'` if $opt_t;
   `$devtools/SetFile -c '$opt_c' '$file'` if $opt_c;
   
   my $newtype = `$devtools/GetFileInfo -t '$file'`;
   chomp( $newtype );
   
   my $newcreator = `$devtools/GetFileInfo -c '$file'`;
   chomp( $newcreator );
   
   print "$newtype   $newcreator  $file\n";
}


[ Reply to This | # ]
A Perl script to manage file types and creators
Authored by: clarkcb on Dec 05, '03 02:01:59PM

Unless Getopt::Std handles this behind the scenes, it looks like one thing is missing from these scripts: passing the file arguments to the glob function to get a list of files from arguments like '*.txt':


@files = ();
foreach $arg (@ARGV) {
    push @files, glob($arg);
}


[ Reply to This | # ]
A Perl script to manage file types and creators
Authored by: dierauer on Dec 05, '03 02:14:14PM

I don't understand why you'd need to do this; for something like '*.txt', the shell will pass the list of files to perl.

Please give more details.



[ Reply to This | # ]
A Perl script to manage file types and creators
Authored by: clarkcb on Dec 05, '03 05:55:55PM

Oops, you're right, sorry. I don't recall why now, but I used to have to do this. Anyway, please disregard previous post.



[ Reply to This | # ]
A Perl script to manage file types and creators
Authored by: hamarkus on Dec 05, '03 07:39:25PM

Stupid question, what is the path on Mac OS X? (I know, the path is where the OS or a programm looks for (executable) files, but where is that on OS X?)



[ Reply to This | # ]
A Perl script to manage file types and creators
Authored by: vonleigh on Dec 06, '03 04:17:20AM
echo $PATH
v

[ Reply to This | # ]
one-liner for bash prompt
Authored by: dfe on Dec 05, '03 11:42:48PM

I guess what they say about PERL programmers is true after all. :-) You can do this with a shell command that can be typed at the bash prompt. If you prefer tcsh then it will be slightly different.

for i in *.txt; do /Developer/Tools/SetFile -t 'TEXT' -c 'ALFA' "$i"; done

You can of course use -t or -c by itself, or you can use any of the 3 other options. There's also an even more handy method for finding files other than by basic shell globbing:

find . -type f -name '*.xml' -exec /Developer/Tools/SetFile -t 'TEXT' -c 'CWIE' {} \;

That will find all entries in the current directory (.) and its subdirectories that are regular files (i.e. not directories, symlinks, or device special) that match the shell glob '*.xml'. For each flie found it will execute the command replacing {} with the name of the file. A semicolon terminates the parameters to the -exec option and must be backslash escaped (or surrounded in quotes like ';') because otherwise the shell interprets it (as it does in the for command above).

One feature I can see with this PERL script is that it does both GetFileInfo and SetFile in one command. For that you'd want to check if the user specified any options then run SetFlie and if the user didn't then run GetFileInfo

Also, /Developer/Tools is not by default on the PATH so the PERL script won't even work out of the box.



[ Reply to This | # ]
one-liner for bash prompt
Authored by: hamarkus on Dec 06, '03 02:05:28PM

Another stupid question, how do I add /Developer/Tools to the path? I have found some instructions
<a href="http://www.informit.com/isapi/product_id~%7B73676503-9D68-4791-A8CA-0DAAFDEECD8D%7D/element_id~%7B56177C72-E3B1-4082-B017-C55F663E14B1%7D/st~%7BFC01C6FA-A166-40A9-BEFF-FA0234A128E9%7D/content/articlex.asp"> here </a>

but there seems to be no .tcshrc nor .profile file on my computer?

(And what am I doing wrong with my link formatting?)



[ Reply to This | # ]
Problem with non-alpha characters
Authored by: Handycam on Dec 06, '03 04:07:46PM

Nice script, except it chokes if the type or creator contains a non-alphabetic character.

For example, try setting the creator of a text file to be BBEdit, code R*ch. Doesn't work.

Can you fix this please?



[ Reply to This | # ]
Use single quotes
Authored by: dierauer on Dec 07, '03 10:08:36AM
Just give the arguments with single quotes: e.g.
tc -t TEXT -c 'R*ch'


[ Reply to This | # ]
A Perl script to manage file types and creators
Authored by: merlyn on Dec 07, '03 11:06:25AM
The scripts I've seen in this thread are safe for filenames that contain space, but dangerous for filenames that contain single-quote or backslash, and sadly they're needlessly dangerous.

Please remember... instead of backquotes, you really want code like:


system 'SetFile', '-c', $creator, @ARGV;
Then, everything is safe, as the names are passed from parent to child without hitting the shell.

I'm willing to preview any Perl script posted here before posting for security and best practice. Please give me a couple of days, and email it to merlyn@stonehenge.com and mention macosxhints. Thanks.

[ Reply to This | # ]

A Perl script to manage file types and creators
Authored by: Handycam on Dec 07, '03 11:33:43AM

Thanks for the tip.

Actually, I fail to see the advantage this script provides over the standard SetFile command,

SetFile -c "R*ch" -t "TEXT" *.html

What would be the advantage in using this script instead?



[ Reply to This | # ]
A Perl script to manage file types and creators
Authored by: mraltivec on Dec 07, '03 05:02:17PM

Advantages over SetFile/GetFileInfo:

1) Easier to type and remember (shorter, no mixed case)

2) Combines GetFileInfo and SetFile functionality into one command

3) Can handle multiple files and wildcards (GetFileInfo does not)

As always, YMMV.



[ Reply to This | # ]