Problem with RunProgram() and quotes

Mac OSX specific forum
Lebostein
Addict
Addict
Posts: 807
Joined: Fri Jun 11, 2004 7:07 am

Problem with RunProgram() and quotes

Post by Lebostein »

I want to overwrite a comment of an image with exiftool:

Code: Select all

/usr/local/bin/exiftool -overwrite_original -comment="This is a test" image.jpg
with Purebasic this don't work:

Code: Select all

prog$ = "/usr/local/bin/exiftool"
para$ = "-overwrite_original -comment=" + #DQUOTE$ + "This is a test" + #DQUOTE$ + " image.jpg"
RunProgram(prog$, para$, "") ; dont work, the image comment is only "This"
Debug prog$ + " " + para$ ; past and run on command line, works
infratec
Always Here
Always Here
Posts: 6866
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Problem with RunProgram() and quotes

Post by infratec »

The best way to test this stuff is to write a program in PB which prints the received parameters:

Code: Select all

OpenConsole()
For i = 0 To CountProgramParameters() - 1
  PrintN(Str(i) + ": " + ProgramParameter(i))
Next i
CloseConsole()
Compile it as console program and call it instead of exif.
AZJIO
Addict
Addict
Posts: 1355
Joined: Sun May 14, 2017 1:48 am

Re: Problem with RunProgram() and quotes

Post by AZJIO »

Code: Select all

prog$="bash"
https://www.purebasic.fr/english/search ... mit=Search

infratec
The exiftool utility can interpret parameters in its own way, not like PureBasic

It is not clear what is the real path to the working directory. For a terminal, this is the home directory, while for code in the compiler, this may be the tmp folder.

Code: Select all

SetCurrentDirectory(GetHomeDirectory())
infratec
Always Here
Always Here
Posts: 6866
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Problem with RunProgram() and quotes

Post by infratec »

AZJIO wrote: Mon Apr 04, 2022 10:10 pm The exiftool utility can interpret parameters in its own way, not like PureBasic
I don' interprete the parameters with my code. I simply show the parameters how they arrive.
And this way is for all executables the same.
Marc56us
Addict
Addict
Posts: 1479
Joined: Sat Feb 08, 2014 3:26 pm

Re: Problem with RunProgram() and quotes

Post by Marc56us »

Hi Lebostein,

This doesn't directly answer the question, but if you want to read or write a JPG comment, you can do so with a few lines of PB. So you can make your own command line tool that will only take 25kb instead of the 8.4MB of exiftool.
Yes, libs exist, but it's often more stimulating to (re)make it yourself.

The comment is written at the beginning of the file, search tags ($FF then $FE). The file does not need to be recompressed after modification.

Structure header: https://en.wikipedia.org/wiki/JPEG#Syntax_and_structure

Comment is set with:
1. Marker: $FF (tag of field)
2. Marker: $FE (Comment)
3. Size of comment (2 bytes, indianless)
4. Comment (Utf-8 fill with $00) max 64k
5. Next $FF

Basic method (without using any lib: Yes PB do all)

Read comment:
Search for $FF then $FE, read size (2 next bytes), read comment (with size or until found \0)
(This is a null-terminated string, so no need to read size: read with ReadString will stop at first \0)

Write comment:
1. Search if comment still exist (if exist, overwrite size and text. Use Loc to keep read position if comment exist)
2. Open New file for writing
3. Read block from source file until $FF
4. Write this block to destination file
5. Write $FF, $FE
6. Write Size of new string
7. Write (new) comment
8. Read rest of source file and write it to destination file
9. Close Source file and destination file (keep source as backup, like Exifttool do or delete if)

Keywords
- ReadFile, ReadByte, FileSeek, Loc, CreateFile, ReadData, WriteData, WriteCharacter, WriteByte, WriteString, CloseFile
you can probably also do it with Peek, Poke and pointer, but I still don't understand much about it, so I stay with the classic functions (read, write, fileseek)

Example of reading (only simples PB functions)

Code: Select all

EnableExplicit
If ReadFile(0, "image.jpg")
    While Not Eof(0)
        If ReadCharacter(0) = $FEFF         ; Search comment tag 
            FileSeek(0, 1, #PB_Relative) 
            MessageRequester("Comment", 
                             ReadString(0, #PB_UTF8, ReadByte(0) -2), 
                             #PB_MessageRequester_Info)
            Break
        EndIf
    Wend
    CloseFile(0)
Else
    MessageRequester("Error", "File Not Found", #PB_MessageRequester_Error)
EndIf
Enjoy
:wink:
Lebostein
Addict
Addict
Posts: 807
Joined: Fri Jun 11, 2004 7:07 am

Re: Problem with RunProgram() and quotes

Post by Lebostein »

AZJIO wrote: Mon Apr 04, 2022 10:10 pm

Code: Select all

prog$="bash"
https://www.purebasic.fr/english/search ... mit=Search

infratec
The exiftool utility can interpret parameters in its own way, not like PureBasic

It is not clear what is the real path to the working directory. For a terminal, this is the home directory, while for code in the compiler, this may be the tmp folder.

Code: Select all

SetCurrentDirectory(GetHomeDirectory())
You mean I should use "bash" for the program parameter and the executable of the program is the first parameter??? This contradicts the PB-manual... Would this then apply to all command line programs on Mac or is this specifically only about exiftool?
AZJIO
Addict
Addict
Posts: 1355
Joined: Sun May 14, 2017 1:48 am

Re: Problem with RunProgram() and quotes

Post by AZJIO »

Lebostein wrote: Wed Apr 06, 2022 8:59 amYou mean I should use "bash" for the program parameter and the executable of the program is the first parameter???
Yes. If it works in the terminal, try running through the terminal.
Lebostein
Addict
Addict
Posts: 807
Joined: Fri Jun 11, 2004 7:07 am

Re: Problem with RunProgram() and quotes

Post by Lebostein »

AZJIO wrote: Wed Apr 06, 2022 9:01 am
Lebostein wrote: Wed Apr 06, 2022 8:59 amYou mean I should use "bash" for the program parameter and the executable of the program is the first parameter???
Yes. If it works in the terminal, try running through the terminal.
Thanks. But why this very important thing is not noted in the PureBasic manual?
Marc56us
Addict
Addict
Posts: 1479
Joined: Sat Feb 08, 2014 3:26 pm

Re: Problem with RunProgram() and quotes

Post by Marc56us »

Thanks. But why this very important thing is not noted in the PureBasic manual?
Because it is specific to certain commands on un*x systems (MacOS is BSD based, so un*x))
For exiftool, the Windows version is a compiled executable. (so RunProgram("exiftool", "parameters"... works)
The Unix and Mac version of exiftool are scripts (perl) encapsulated or not with the perl runtime if it is already present or not.
See details on https://exiftool.org/install.html
As these two versions are scripts, they must be launched in/by a shell (bash, sh, zsh, ksh etc)
I don't have a mac, but I see that linux version have a shebang in main script (#!/usr/bin/perl -w). I thing RunProgram not read this line, but shell (bash) do it.
If you are in a terminal, the shell is already open. (compile as Console Mode, RunProgram("exiftool", "...) will works.
If you run the script directly, then you have to open a shell first. RunProgram("sh", "exiftool ...")
(It is like a 'cmd', "/c ..." under Windows)
Note: to ensure compatibility in programs, it is better to use 'sh' rather than 'bash'.
'sh' is a symbolic link to the shell defined for the user. The command line will automatically adapt to whatever shell the user is using.
You can put 'sh' in any case, but this will have the effect of opening a shell in a shell, thus losing ram and the environment variables of the first shell
Post Reply