Page 1 of 1

Make cross-platform readable file names

Posted: Tue Jan 04, 2011 9:27 pm
by Little John
Works also with PB 5.20

Hi all,

if you have created files with Linux e.g. on a FAT32 drive, then it might happen that it's not possible to access (open, copy etc.) some of them with Windows, because Windows cannot read certain characters in file names. If necessary, the following small Linux program changes names in a directory and all its subdirectories, so that they are cross-platform readable.

Code: Select all

; -- RenameXplat
; -- Version 1.0, 2011-01-03
; Public Domain, written by Juergen Luethje <http://luethje.eu/>.
; Developed with Purebasic 4.51.
; Cross-platform, Unicode compliant.
; Tested on Ubuntu 10.10 x86.
; Standard disclaimer: USE AT YOUR OWN RISK!
;
; according to <http://en.wikipedia.org/wiki/Filename>, 2011-01-03

EnableExplicit

#TITLE$ = "RenameXplat 1.0"
#SLASH$ = "/"

; Forbidden characters in directory and file names on Windows
#BAD_TRAILING = " ."
#BAD_ANYWHERE = ":/\?*<>|" + #DQUOTE$


Procedure.i RenameXplat (path$)
   ; -- Look for directory and file names that are not cross-platform
   ;    readable in 'path$' and all subdirectories, and rename them
   ;    (replace each bad character with '_').
   ; in : path with trailing slash
   ; out: return value: number of changed names, or -1 on error
   Protected *endPntr, *char.Character, id, altered, exitCode, count=0
   Protected name$

   id = ExamineDirectory(#PB_Any, path$, "")
   If id = 0
      ProcedureReturn -1                      ; error, stop processing
   EndIf

   While NextDirectoryEntry(id)
      name$ = DirectoryEntryName(id)
      If FindString("..", name$, 1)
         Continue
      EndIf

      ; -- Visit any subdirectory recursively
      If DirectoryEntryType(id) & #PB_DirectoryEntry_Directory
         exitCode = RenameXplat(path$ + name$ + #SLASH$)
         If exitCode = -1
            FinishDirectory(id)
            ProcedureReturn -1                ; error, stop processing
         Else
            count + exitCode
         EndIf
      EndIf

      ; -- Rename any bad entry (directory or file)
      altered = #False
      
      ; Replace characters that are harmful at the end of the name
      *endPntr = @name$ + (Len(name$)-1)*SizeOf(Character)
      For *char = *endPntr To @name$ Step -SizeOf(Character)
         If FindString(#BAD_TRAILING, Chr(*char\c), 1)
            *char\c = '_'
            altered = #True
         Else
            Break
         EndIf
      Next
      
      ; Replace characters that are harmful anywhere in the name
      *endPntr = *char
      For *char = *endPntr To @name$ Step -SizeOf(Character)
         If (*char\c < 32) Or FindString(#BAD_ANYWHERE, Chr(*char\c), 1)
            *char\c = '_'
            altered = #True
         EndIf
      Next
      
      If altered
         If RenameFile(path$ + DirectoryEntryName(id), path$ + name$) = 0
            FinishDirectory(id)
            ProcedureReturn -1                ; error, stop processing
         Else
            count + 1
         EndIf
      EndIf
   Wend

   FinishDirectory(id)
   ProcedureReturn count
EndProcedure


Define Count
Define Path$, Msg$

If CountProgramParameters() <> 1
   MessageRequester(#TITLE$, "(c) Jürgen Lüthje 2011" + #LF$ + #LF$ + "Usage: RenameXplat <path>")
   End
EndIf

Path$ = ProgramParameter(0)
Msg$ = "Path '" + Path$ + "'"

If FileSize(Path$) <> -2
   MessageRequester(#TITLE$, Msg$ + " not found.")
   End
EndIf

If Right(Path$, 1) <> #SLASH$
   Path$ + #SLASH$
EndIf

Count = RenameXplat(Path$)

If Count = -1
   MessageRequester(#TITLE$, Msg$ + ":" + #LF$ + "Error.")
Else
   MessageRequester(#TITLE$, Msg$ + ":" + #LF$ + Str(Count) + " name(s) changed.")
EndIf
Regards, Little John