#lang scribble/manual @(require (for-label racket)) @title{PathName} file and directory path utilities@section{related} Classes/File, Classes/String @section{categories} Files @section{description} PathName is a utility class for manipulating file names and paths. It expects a path to a file, and lets you access parts of that file path. @section{ClassMethods} @section{private} initClass @section{method} new @section{argument} path a link::Classes/String:: which likely contains one or more / as typical for folder separation. ~ will be converted to your fully addressed home directory, as per link::Classes/String#-standardizePath::. @racketblock[ PathName.new("MyDisk/SC 2.2.8 f/Sounds/FunkyChicken"); :: ] @section{method} tmp Get or set the global temp directory as a link::Classes/String::. This is used by link::Classes/Buffer::, etc. By default this is "/tmp/" for Linux and macOS, and "/WINDOWS/TEMP/" for Windows. @section{InstanceMethods} @section{method} fileName returns just the name of the file itself; i.e. everything after the last slash in the full path. @racketblock[ ( var myPath; myPath = PathName.new("MyDisk/SC 2.2.8 f/Sounds/FunkyChicken"); myPath.fileName.postln; ) :: ] @section{method} fileNameWithoutExtension returns the name of the file itself without the file extension. @section{method} extension returns the file extension, i.e. everything after the last full-stop in the link::#-fileName::. @section{method} pathOnly returns the full path up to the file name itself; i.e. everything up to and including the last slash. This is handy e.g. for storing several files in the same folder. @racketblock[ ( var myPath; myPath = PathName.new("MyDisk/SC 2.2.8 f/Sounds/FunkyChicken"); myPath.pathOnly.postln; ) :: ] @section{method} isAbsolutePath, asAbsolutePath, isRelativePath, asRelativePath you MUST have correctly initialized the scroot classvar for this to know what it is relative to ! @section{method} folderName returns only the name of the folder that the file is in; i.e. everything in between the last but one and the last slash. @racketblock[ ( var myPath; myPath = PathName.new("MyDisk/SC 2.2.8 f/Sounds/FunkyChicken"); myPath.folderName.postln; ) :: ] @section{method} fullPath returns the full path name that PathName contains. @racketblock[ ( var myPath; myPath = PathName.new("MyDisk/SC 2.2.8 f/Sounds/FunkyChicken"); myPath.fullPath.postln; ) :: ] @section{method} entries returns a list of all the files+folders inside the folder represented by this path. @racketblock[ ( var myPath; myPath = PathName.new("./"); myPath.entries.postln; ) :: ] @section{method} files returns a list of all the files in the folder represented by this path. @racketblock[ ( var myPath; myPath = PathName.new("./"); myPath.files.postln; ) :: ] @section{method} folders returns a list of all the subfolders of the folder represented by this path. @racketblock[ ( var myPath; myPath = PathName.new("./"); myPath.folders.postln; ) :: ] @section{method} isFile returns a link::Classes/Boolean:: indicating whether or not the path represents a file (not a folder). @racketblock[ ( var myPath; myPath = PathName.new("./"); myPath.isFile.postln; ) :: ] @section{method} isFolder returns a link::Classes/Boolean:: indicating whether or not the path represents a folder (not a file). @racketblock[ ( var myPath; myPath = PathName.new("./"); myPath.isFolder.postln; ) :: ] @section{method} filesDo Iterates over all files found in the pathname, including ones in subfolders. @racketblock[ ( var myPath; myPath = PathName.new("./"); myPath.filesDo{|afile| afile.postln}; ) :: ] @section{method} allFolders returns a list of all the folder names contained in the pathname itself. @racketblock[ ( var myPath; myPath = PathName.new("MyDisk/SC 2.2.8 f/Sounds/FunkyChicken"); myPath.allFolders.postln; ) :: ] @section{method} diskName if path is an absolute path, returns the disk name; else a blank string. @racketblock[ ( var myPath; myPath = PathName.new("MyDisk/SC 2.2.8 f/Sounds/FunkyChicken"); myPath.diskName.postln; ) ( // note the / at the start var myPath; myPath = PathName.new("/MyDisk/SC 2.2.8 f/Sounds/FunkyChicken"); myPath.diskName.postln; ) :: ] @section{method} +/+ Path concatenation operator - useful for avoiding doubling-up slashes unnecessarily. @racketblock[ (PathName("/somewhere") +/+ PathName("over/the/rainbow")).postln; (PathName("/somewhere") +/+ PathName("/over/the/rainbow")).postln; :: ] @section{method} endNumber returns a number at the end of PathName. Returns zero if there is no number. @racketblock[ PathName("floating1").endNumber.postln; PathName("floating").endNumber.postln; :: ] @section{method} noEndNumbers returns link::#-fullPath:: without any numbers at the end. @racketblock[ PathName("floating1").noEndNumbers.postln; PathName("floating").noEndNumbers.postln; :: ] @section{method} nextName generates a sensible next name for a file by incrementing a number at the end of PathName, or by adding one if there is none. This is useful for recording files with consecutive names, and e.g. to generate a new filename when you don't want to overwrite an existing file with the current name. @racketblock[ PathName("floating34").nextName.postln; PathName("floating").nextName.postln; PathName("floating12_3A4X_56.7").nextName.postln; :: ] @section{Examples} Here is an example that uses many instance methods. Just pick any file to see all the parts of its path. @racketblock[ ( GetFileDialog.new( { arg ok, path; var myPathName; if (ok, { myPathName = PathName.new(path); "New PathName object: ".postc; myPathName.postln; "fileName only: ".postc; myPathName.fileName.postln; "path up to file only: ".postc; myPathName.pathOnly.postln; "folder Name: ".postc; myPathName.folderName.postln; } ) } ) ) :: Choose a soundfile to put into the library, using its foldername and filename. ] @racketblock[ ( GetFileDialog.new( { arg ok, path; var myPathName, myFile; if (ok, { myPathName = PathName.new(path); // read your file from disk, e.g. a soundFile/ myFile = SoundFile.new; if (myFile.openRead(path), { Library.put( [ myPathName.folderName.asSymbol, myPathName.fileName.asSymbol ], myFile); ("Check Library.global" + myPathName.folderName + "please.").postln; }, { ("Could not read soundfile" + path ++ ".").postln; } ); myFile.close; } ) } ) ) :: Save three tables in the same folder. Note: The file name chosen in the dialog is ignored! The files are always named table1, table2, table3. ] @racketblock[ ( var table1, table2, table3; table1 = Wavetable.sineFill(1024, [1,2,3]); table2 = Signal.newClear.asWavetable; table3 = Wavetable.sineFill(1024, Array.rand(64, 0.0, 1.0)); GetFileDialog.new( { arg ok, path; var myPathName, myPathOnly; if (ok, { myPathName = PathName.new(path); myPathOnly = myPathName.pathOnly; ("writing files tables1-3 to"+myPathOnly).postln; table1.write(myPathOnly ++ "table1"); table2.write(myPathOnly ++ "table2"); table3.write(myPathOnly ++ "table3"); } ) } ) ) :: ]