Recent

Author Topic: [SOLVED]Bash commands and scripts in Lazarus.  (Read 7911 times)

johnathan

  • New Member
  • *
  • Posts: 14
[SOLVED]Bash commands and scripts in Lazarus.
« on: October 17, 2023, 07:55:02 pm »
Hi
Can anybody help

I would like to run bash and/or bash script from within Lazarus if this is possible.

Things I am already able to do in Lazarus.
Read a text file into a filelistbox and process the information in Lazarus for example rename a list of files to another directory.

As a starter I would like to run the following bash command from inside a Lazarus program. I will not be affended if it is very simple as it needs to be for me.
Obviously  the bash command can be run externally and then load the file into Lazarus or read the file names from a filelistbox into a listbox but I would like try to expand my use of Lazarus.

(bash command)    ls -1 >  /mnt/trials/fileslist.txt 

If you can help many thanks

john

« Last Edit: November 01, 2023, 12:52:38 pm by johnathan »

TRon

  • Hero Member
  • *****
  • Posts: 3647
Re: Bash commands and scripts in Lazarus.
« Reply #1 on: October 18, 2023, 01:19:29 am »
I would like to run bash and/or bash script from within Lazarus if this is possible.
Yes, that is possible. See wiki executing external commands.

Quote
(bash command)    ls -1 >  /mnt/trials/fileslist.txt 
Especially the piping that you show there is making things overly complicated for nothing. You can 'catch' the output from an external command yourself.

I made up some simple example (showing some variations) for Free Pascal using RunCommand (afaik the most simplified version to run an external command that also 'catches' the output). It can easily be integrated into your Lazarus project. The resulting output is by default stored in a string that you can assign to a memo (property text) or added to a memo.

Code: Pascal  [Select][+][-]
  1. program run;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   classes, process;
  7.  
  8. procedure dodo;
  9. const
  10.   cmd_ls    = '/bin/ls';
  11.   cmd_bash  = '/bin/bash';
  12.   cmd_chmod = 'chmod';
  13. var
  14.   rc_result: string;
  15.   Line: string;
  16.   Lines: TStringList;
  17. begin
  18.   // run ls command directly (with full path)
  19.   writeln('>$ ', cmd_ls, ' -l');
  20.   if RunCommand(cmd_ls, ['-l'], rc_result) then
  21.   begin
  22.     writeln('output:');
  23.     writeln(rc_result);
  24.     writeln;
  25.     writeln('alternative way of output:');
  26.     Lines := TStringList.Create;
  27.     Lines.Text := rc_result;
  28.     for Line in Lines
  29.       do Writeln(Line);
  30.     Lines.Free;
  31.   end
  32.   else writeln('error running command ', cmd_ls);
  33.   writeln;
  34.  
  35.   // run s command directly (without path)
  36.   writeln('>$ ', 'ls -l');
  37.   if RunCommand('ls', ['-l'], rc_result) then
  38.   begin
  39.     writeln('output:');
  40.     writeln(rc_result);
  41.   end
  42.   else writeln('error running command ', 'ls -l');
  43.   writeln;
  44.  
  45.   // run ls command using bash
  46.   writeln('>$ ', cmd_bash, ' -c ls -l');
  47.   if RunCommand(cmd_bash, ['-c', 'ls -l'], rc_result) then
  48.   begin
  49.     writeln('output:');
  50.     writeln(rc_result);
  51.   end
  52.   else writeln('error running command ', cmd_bash);
  53.   writeln;
  54.  
  55.   // run bash internal command
  56.   writeln('>$ ', cmd_bash, ' -c compgen -b');
  57.   if RunCommand(cmd_bash, ['-c', 'compgen -b'], rc_result) then
  58.   begin
  59.     writeln('output:');
  60.     writeln(rc_result);
  61.   end
  62.   else writeln('error running command ', cmd_bash);
  63.   writeln;
  64.  
  65.   // create a bash script file
  66.   writeln('creating hello.sh script');
  67.   Lines := TStringList.Create;
  68.   Lines.Add('#! ' + cmd_bash);
  69.   Lines.Add('echo "Hello bash"');
  70.   Lines.SaveToFile('hello.sh');
  71.   Lines.Free;
  72.   writeln;
  73.  
  74.   // run chmod commnand directly (without path) to make the script executable
  75.   writeln('>$ ', cmd_chmod, ' u+x hello.sh');
  76.   if RunCommand(cmd_chmod, ['u+x', 'hello.sh'], rc_result) then
  77.   begin
  78.     Writeln('modified bash script file permissions');
  79.   end
  80.   else writeln('error running command ', cmd_chmod, ' unable to modify file permissons');
  81.   writeln;
  82.  
  83.   // run the script directly
  84.   writeln('>$ ', 'hello.sh');
  85.   if RunCommand('hello.sh', [], rc_result) then
  86.   begin
  87.     writeln('output:');
  88.     writeln(rc_result);
  89.   end
  90.   else writeln('error running script');
  91.   writeln;
  92. end;
  93.  
  94. begin
  95.   dodo;
  96. end.
  97.  

I am not 100% sure if running it from Lazarus requires the full path to the commands that are being executed (it works when started from a bash terminal window) but you'll notice that soon enough and can easily be fixed if that would to be the case.

Seeing that you do not have many posts icw your question, I assume you are new to Lazarus in which case note that writeln's do not work with Lazarus unless you start your Lazarus application form a terminal window. If you want to 'fix' that then replace the writeln's with adding the strings to a memo or stringlist (or whatever is most convenient for your application)
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

johnathan

  • New Member
  • *
  • Posts: 14
Re: Bash commands and scripts in Lazarus.
« Reply #2 on: October 23, 2023, 07:16:27 pm »
Hi
Thanks for the reply. I have not had any success so far but will continue to experiment.
I notice that runcommand has been depreciated in Linux which could be a problem.
Meanwhile I have no trouble using bash to generate  ".txt" with bash to obtain the data I require and using Linux Lazarus IDE to process the data within them.

Thanks for your time

john

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11944
  • FPC developer.
Re: Bash commands and scripts in Lazarus.
« Reply #3 on: October 23, 2023, 08:54:58 pm »

I notice that runcommand has been depreciated in Linux which could be a problem.

Runcommand is not deprecated, some older forms of the command are deprecated in favor of newer ones.

TRon

  • Hero Member
  • *****
  • Posts: 3647
Re: Bash commands and scripts in Lazarus.
« Reply #4 on: October 24, 2023, 11:01:26 am »
Thanks for the reply. I have not had any success so far but will continue to experiment.
You would have to be more specific than that in case you require additional help. All I can say is that it works for me tm (with Lazarus as well).

Quote
I notice that runcommand has been depreciated in Linux which could be a problem.
As stated by marcov, only a specific version of runcommand, see also manual :

Quote
The version using CmdLine attempts to split the command line in a binary and separate command-line arguments. This version of the function is deprecated.

Quote
Meanwhile I have no trouble using bash to generate  ".txt" with bash to obtain the data I require and using Linux Lazarus IDE to process the data within them.
And I emphasize again that runcommand returns the output of the command into a string (no matter how many lines that output contains as the line separators are part of that one string as well), so there would be no need to use bash and/or pipe the output from the executed command to a textfile to then have to read it in order to do something with the output.

See also attachment.
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

johnathan

  • New Member
  • *
  • Posts: 14
Re: Bash commands and scripts in Lazarus.
« Reply #5 on: October 30, 2023, 11:06:03 pm »
Hi

A few more details as suggested.
Please note I am only a desktop computer user having never been involved in the computer industry.

Reason for program:
I have several hundred (.flac) audio files which have file names in sequence af10001 af10002 etc.

Aim:
To produce a set of file names to replace the original file with a new file name, “POSIX compatible”, consisting of the title, and preserving the original file.
Then to change the title data in the new file combining the title and artist.

Progress:
While experimenting with theis I have copied just a few of the files to a separate folder for “safety”
1.   I have extracted the metadata from all files to give  3 text files (.txt)    with lists of, file names, title, artist. For this I have written a bash    script using metaflac command.
2.   Loading the 3 text files into Lazarus as stringlists and then processing them. I have generated the required file names and renamed and saved them, also generating a text file containing list of the new titles.

Todo:
Write a bash script using metaflac to delete the original title metadata in the new file and to replace it with the new title.

I needed to know if I could run a “bash command” and/or “bash script” within Lazarus rather the having to switch from one to the other. To do this and not having a great deal of experience I started by asking something simple
eg.
(bash command) ls -1 > /mnt/trials/fileslist.txt

Thanks
john
« Last Edit: October 30, 2023, 11:15:01 pm by johnathan »

TRon

  • Hero Member
  • *****
  • Posts: 3647
Re: Bash commands and scripts in Lazarus.
« Reply #6 on: October 31, 2023, 07:35:59 pm »
Progress:
While experimenting with theis I have copied just a few of the files to a separate folder for “safety”
1.   I have extracted the metadata from all files to give  3 text files (.txt)    with lists of, file names, title, artist. For this I have written a bash    script using metaflac command
2.   Loading the 3 text files into Lazarus as stringlists and then processing them. I have generated the required file names and renamed and saved them, also generating a text file containing list of the new titles.
My example was made with the intention to show you that it is not necessary to use a bash script, nor that it is necessary to store the output of that script to (separate) files. You can execute the metaflac terminal command directly using runcomand and 'catch' its output into a string and/or store that string into a stringlist. That is what you should be able to get/understand from the posted example (albeit the example uses other terminal commands to show different approaches).

Quote
Todo:
Write a bash script using metaflac to delete the original title metadata in the new file and to replace it with the new title.
Sorry to have to be persistent in my answer but there is no need to create a bash script. You can if you must and/or want to but really it is making things complicated for nothing.

Quote
I needed to know if I could run a “bash command” and/or “bash script” within Lazarus rather the having to switch from one to the other. To do this and not having a great deal of experience I started by asking something simple
eg.
(bash command) ls -1 > /mnt/trials/fileslist.txt
And the answer to that particular question is yes you can.

The part what I do not understand is that you wrote that you do rather not want to switch between one or another. I read that as: you do not want to switch between running a bash command and/or running a bash
script. If you leave out bash from the equation then the only thing left is to run the terminal commands directly and you can do that as showed per my example.

My example is/was meant to show that you can use any of the 3 approaches:
- run a terminal command directly (not using bash or scripts)
- run a command using/through bash
- run a shell/terminal script

So you can choose whatever approach is more convenient for you.

Or to put it into other words: I still have no clue what it is that you actually have a problem with.

Am I perhaps confusing you by the fact that I stated that this is a Free Pascal example that requires to be started using a terminal ?

Because that is only required for the writeln's so that the example is able to provide some feedback on what is happening. For such simple examples I use Free Pascal and not Lazarus (that is why I posted a picture of a Lazarus example using the same code but then uit outputs the result(s) to a TMemo control instead). So that picture is from a pure desktop only application (with the exception that it relies on the OS to provide us access to the terminal (commands)).
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

johnathan

  • New Member
  • *
  • Posts: 14
Re: Bash commands and scripts in Lazarus.
« Reply #7 on: November 01, 2023, 12:51:46 pm »
Hi again.
Thanks for all your input and your patience for those of us who have a limited ability and knowledge.

I will mark the topic as SOLVED as the initial question has been answered ie can bash be used in Lazarus IDE.

The term “switch” was used to indicate that I would like to remain within the Lazarus IDE but would use either “bash or bash script”.

I have printed off your replies and will continue to try and understand how it works.

Thanks again for your input

Regards john

TRon

  • Hero Member
  • *****
  • Posts: 3647
Re: Bash commands and scripts in Lazarus.
« Reply #8 on: November 03, 2023, 09:48:16 pm »
The term “switch” was used to indicate that I would like to remain within the Lazarus IDE but would use either “bash or bash script”.
The example shows that both are possible.

Quote
I have printed off your replies and will continue to try and understand how it works.
If you have a specific question then please elaborate.

I am not familiar with metaflac (though I tried as soon as you mentioned the command for the first time) but you can execute it directly from within Lazarus (just like the example: "run ls command directly" either with full path or without, just replacing ls with metaflac, using bash or otherwise)

The metaflac command itself is a bit peculiar with accepting some parameters because of the quoting style it seem to require for some arguments f.e. --set-tag=field where field is declared as "NAME=VALUE" (note the quotes, they seem to be mandatory and can cause issues with runcommand when those quotes are not applied correctly which for example seems to be --set-tag="artist=some artist name" and not --set-tag=artist="some artist name" or "--set-tag=artist=some artist name").

Quote
Thanks again for your input
You're welcome though I have a feeling that you are still struggling with either the code or the concept.

Please don't hesitate to ask but do not expect others to write code for you especially when not providing any example code (if even a metaflac example commandline or bash script that could be converted to Pascal using only runcommand (using bash or otherwise).

Do note that I expressed why using your ls piped ls example code (which can literally be executed with runcommand using bash or sh) is a bad idea and I therefor deem it as a not so good example to show what you are intending to accomplish when looking at the whole picture.
« Last Edit: November 03, 2023, 10:39:48 pm by TRon »
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

johnathan

  • New Member
  • *
  • Posts: 14
Re: [SOLVED]Bash commands and scripts in Lazarus.
« Reply #9 on: November 30, 2023, 01:17:57 pm »
Hi Again
As you have said  I am  still struggling with either the code or the concept.

I have now completed my aim to process hundreds of ".flac" files and all my programs/scripts work perfectly as required.
I have not given up hope of making this a single program and will spend continue to try and master it.

My bash script "bashmusic.sh generates all the required data in ".txt" files to load into the Lazarus executable.

My Lazarus executable  "musictitles5"  then processes the data to be used for changing the metadata in the files and renaming them  files with  "POSIX"  compatible filenames.

My bash script "trial07.sh" then changes the metadata moves the processed files to the required directories and cleans the used temporary directories and temporary .txt files.

Thanks  for the all the input

John



TRon

  • Hero Member
  • *****
  • Posts: 3647
Re: [SOLVED]Bash commands and scripts in Lazarus.
« Reply #10 on: November 30, 2023, 06:23:52 pm »
As you have said  I am  still struggling with either the code or the concept.
Like said, if you have hands on practical (bash) code that you want converted then show us. Without it, it is nearly impossible to come up with an example that matches your needs/requirements simply because we do not know what those needs/requirements are.

All I can say for now is that everything bash can do, Pascal and/or Lazarus can do ranging from executing commands to processing directories/files recursively matching a certain mask, retrieving the output from commands and processing that output to feed to another command etc.
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

johnathan

  • New Member
  • *
  • Posts: 14
Re: [SOLVED]Bash commands and scripts in Lazarus.
« Reply #11 on: December 02, 2023, 04:46:02 pm »
Hi

For now I will be busy running my program and scripts to process some of the hundreds of  .flac files i have.

Hopefully in the new year I will try again to work out what I need to do.

Attached is the bash script that I use to produce the input for my Lazarus program.
It may not be good programming, as I have only been writing scripts for a few months, but it does exactly what I need.

I tried to attach as a libreoffice .odt file before I found that that format was not allowed.

Regards john

TRon

  • Hero Member
  • *****
  • Posts: 3647
Re: [SOLVED]Bash commands and scripts in Lazarus.
« Reply #12 on: December 03, 2023, 02:52:35 am »
Attached is the bash script that I use to produce the input for my Lazarus program.
Something to work with...

Quote
It may not be good programming, as I have only been writing scripts for a few months, but it does exactly what I need.
That doesn't really matter. If you wish to do it purely in Lazarus then it requires a different angle/mindset to solve/approach the issue.

Code: Bash  [Select][+][-]
  1. oldnumber=""
  2. while IFS= read -r line ; do
  3. oldnumber=("$line")
  4. done < "$data2/music29.txt"
  5. echo "old batch number " $oldnumber
  6. echo
  7. echo enter batch
  8. read batch
  9. runnumber=$batch
  10.  
I have no idea what this first part of your bash script does or is suppose to be doing so I needed to skip that part,

The rest of your bash script can be converted to pascal with:
Code: Pascal  [Select][+][-]
  1. program bashbash;
  2.  
  3. {$mode objfpc}{$H+}
  4. {.$define mysetup} // for my personal setup not matching yours.
  5.  
  6. // https://forum.lazarus.freepascal.org/index.php/topic,64932.0.html
  7. // https://wiki.freepascal.org/FindAllFiles
  8.  
  9. uses
  10.   classes, process, fileutil, sysutils;
  11.  
  12. const
  13.   {$ifdef mysetup}
  14.   source = './flacs';
  15.   {$else}
  16.   source = '/mnt/music/bashmusic/source1';
  17.   {$endif}
  18.   FindRecursive = false;  // search source directory recursively for flac files (true (=yes)/false (=no)). Your batch file doesn't.
  19.  
  20.  
  21. procedure Print(s: string); overload;
  22. begin
  23.   {$ifdef mysetup}
  24.   writeln(s);
  25.   {$else}
  26.   // in case you wish to use lazarus and display the output to a memo
  27.   // then your code should be looking something like:
  28.   Form1.InfoMemo.Append(s);
  29.   {$endif}
  30. end;
  31.  
  32. procedure Print(s: string; const args: array of const); overload;
  33. begin
  34.   print(Format(s, args));
  35. end;
  36.  
  37.  
  38. procedure test;
  39. var
  40.   FileNames: TStringList;
  41.   Filename : string;
  42.  
  43.   command  : string;
  44.   parameter: string;
  45.   rc_result: string;
  46.  
  47.   Artist: string;
  48.   Title : string;
  49.   Album : string;
  50. begin
  51.   // create a stringlist that will contain the found filenames
  52.   FileNames := TStringList.Create;
  53.   try
  54.     // find all the files in directory source that matches the mask *.flac
  55.     FindAllFiles(Filenames, source, '*.flac', FindRecursive);
  56.     print('found %d files.', [FileNames.Count]);
  57.  
  58.     // iterate through the FileNames list
  59.     // equivalent to your bash line: for filename in $source/*.flac ; do
  60.     for FileName in FileNames do
  61.     begin
  62.       print('');
  63.       print('handling filename %s', [Filename]);
  64.  
  65.       // equivalent of your bash line: metaflac --show-tag=artist $filename
  66.       command   := 'metaflac';
  67.       parameter := '--show-tag=artist';
  68.       if RunCommand(command, [parameter, FileName], rc_result) then
  69.       begin
  70.         Artist := rc_result.TrimRight;
  71.       end
  72.       else print('error running command %s %s', [command, parameter]);
  73.  
  74.       // equivalent of your bash line: metaflac --show-tag=title $filename
  75.       command   := 'metaflac';
  76.       parameter := '--show-tag=title';
  77.       if RunCommand(command, [parameter, FileName], rc_result) then
  78.       begin
  79.         Title := rc_result.TrimRight;
  80.       end
  81.       else print('error running command %s %s', [command, parameter]);
  82.  
  83.       // equivalent of your bash line: metaflac --show-tag=album $filename
  84.       command   := 'metaflac';
  85.       parameter := '--show-tag=album';
  86.       if RunCommand(command, [parameter, FileName], rc_result) then
  87.       begin
  88.         Album := rc_result.TrimRight;
  89.       end
  90.       else print('error running command %s %s', [command, parameter]);
  91.  
  92.       // show the resulting answers:
  93.       print('Filename = %s', [Filename]);
  94.       print('Artist   = %s', [Artist]);
  95.       print('Title    = %s', [Title]);
  96.       print('Album    = %s', [Album]);
  97.     end;
  98.  
  99.   finally;
  100.     FileNames.Free;
  101.   end;
  102. end;
  103.  
  104. begin
  105.   test;
  106. end.
  107.  

I wrote it as a pure Free Pascal command line example but it should be easy enough to copy-paste the interesting parts to your Lazarus project in order to test. Make sure to backup your original project first before tinkering with code from someone else (things might explode :) ).

And the output with a test album:
Code: [Select]
found 9 files.

handling filename flacs/9 - 52nd Street.flac
Filename = flacs/9 - 52nd Street.flac
Artist   = ARTIST=BILLY JOEL
Title    = TITLE=52nd Street
Album    = ALBUM=52ND STREET

handling filename flacs/8 - Until The Night.flac
Filename = flacs/8 - Until The Night.flac
Artist   = ARTIST=BILLY JOEL
Title    = TITLE=Until The Night
Album    = ALBUM=52ND STREET

handling filename flacs/7 - Half A Mile Away.flac
Filename = flacs/7 - Half A Mile Away.flac
Artist   = ARTIST=BILLY JOEL
Title    = TITLE=Half A Mile Away
Album    = ALBUM=52ND STREET

handling filename flacs/6 - Rosalinda's Eyes.flac
Filename = flacs/6 - Rosalinda's Eyes.flac
Artist   = ARTIST=BILLY JOEL
Title    = TITLE=Rosalinda's Eyes
Album    = ALBUM=52ND STREET

handling filename flacs/5 - Stiletto.flac
Filename = flacs/5 - Stiletto.flac
Artist   = ARTIST=BILLY JOEL
Title    = TITLE=Stiletto
Album    = ALBUM=52ND STREET

handling filename flacs/4 - Zanzibar.flac
Filename = flacs/4 - Zanzibar.flac
Artist   = ARTIST=BILLY JOEL
Title    = TITLE=Zanzibar
Album    = ALBUM=52ND STREET

handling filename flacs/3 - My Life.flac
Filename = flacs/3 - My Life.flac
Artist   = ARTIST=BILLY JOEL
Title    = TITLE=My Life
Album    = ALBUM=52ND STREET

handling filename flacs/2 - Honesty.flac
Filename = flacs/2 - Honesty.flac
Artist   = ARTIST=BILLY JOEL
Title    = TITLE=Honesty
Album    = ALBUM=52ND STREET

handling filename flacs/1 - Big Shot.flac
Filename = flacs/1 - Big Shot.flac
Artist   = ARTIST=BILLY JOEL
Title    = TITLE=Big Shot
Album    = ALBUM=52ND STREET

Simply lovely that upcase tagging style  :'(

It might perhaps not be the exact output you are expecting but strings are pretty easy to manipulate and it is fairly easy to extract the bits and pieces that you might be interested in. I can't change what the metaflace tool actually returns (such as the CRLF at the end of the return value when requesting a tag so the code removes it with TrimRight).
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

johnathan

  • New Member
  • *
  • Posts: 14
Re: [SOLVED]Bash commands and scripts in Lazarus.
« Reply #13 on: December 05, 2023, 11:58:02 am »
Hi
Thanks again for all your input.
The first part is just to keep a log of the batches that I process and I could quite easily put this into my Lazarus program.

I tend to convert any data I read into Lazarus to lowercase which keeps things simple for me.

I will as you say backup my original Lazarus project, I tend to do this by saving everything with a new  lpi and pas filenames in a new directory.

I will in due course attempt to use some of your code so that I can use Lazarus only, and will let you know how it goes although it may be in the new year.

Regards  john
 
21st. December 2023
 
Christmas has come early, thanks to your suggestions.
Could not wait for the new year so have started writing  a Lazarus version of some parts of your code into my project.
About half way though adding the (bashmusic2.sh) to my program and so far no problems and works as as required.
It looks like I will be able to run the whole thing from Lazarus now.
I have also added Lazarus code to copy files automatically to the source and destination directories.

My grateful thanks, hope  the new year brings good health to all.

john

« Last Edit: December 21, 2023, 05:17:40 pm by johnathan »

 

TinyPortal © 2005-2018