[SOLVED]Bash commands and scripts in Lazarus. lazarus / 32-Linux ---------------------------------------------------------------------- johnathan · 2023-10-17 17:55 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 ---------------------------------------------------------------------- TRon · 2023-10-17 23:19 Quote from: johnathan on October 17, 2023, 07:55:02 pmI 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program run; {$mode objfpc}{$H+} uses  classes, process; procedure dodo;const  cmd_ls    = '/bin/ls';  cmd_bash  = '/bin/bash';  cmd_chmod = 'chmod';var  rc_result: string;  Line: string;  Lines: TStringList;begin  // run ls command directly (with full path)  writeln('>$ ', cmd_ls, ' -l');  if RunCommand(cmd_ls, ['-l'], rc_result) then  begin    writeln('output:');    writeln(rc_result);  writeln;    writeln('alternative way of output:');    Lines := TStringList.Create;    Lines.Text := rc_result;    for Line in Lines    do Writeln(Line);    Lines.Free;  end  else writeln('error running command ', cmd_ls);  writeln;   // run s command directly (without path)  writeln('>$ ', 'ls -l');  if RunCommand('ls', ['-l'], rc_result) then  begin    writeln('output:');    writeln(rc_result);  end  else writeln('error running command ', 'ls -l');  writeln;   // run ls command using bash  writeln('>$ ', cmd_bash, ' -c ls -l');  if RunCommand(cmd_bash, ['-c', 'ls -l'], rc_result) then  begin    writeln('output:');    writeln(rc_result);  end  else writeln('error running command ', cmd_bash);  writeln;   // run bash internal command  writeln('>$ ', cmd_bash, ' -c compgen -b');  if RunCommand(cmd_bash, ['-c', 'compgen -b'], rc_result) then  begin    writeln('output:');    writeln(rc_result);  end  else writeln('error running command ', cmd_bash);  writeln;   // create a bash script file  writeln('creating hello.sh script');  Lines := TStringList.Create;  Lines.Add('#! ' + cmd_bash);  Lines.Add('echo "Hello bash"');  Lines.SaveToFile('hello.sh');  Lines.Free;  writeln;   // run chmod commnand directly (without path) to make the script executable  writeln('>$ ', cmd_chmod, ' u+x hello.sh');  if RunCommand(cmd_chmod, ['u+x', 'hello.sh'], rc_result) then  begin    Writeln('modified bash script file permissions');  end  else writeln('error running command ', cmd_chmod, ' unable to modify file permissons');  writeln;   // run the script directly  writeln('>$ ', 'hello.sh');  if RunCommand('hello.sh', [], rc_result) then  begin    writeln('output:');    writeln(rc_result);  end  else writeln('error running script');  writeln;end; begin  dodo;end.  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) ---------------------------------------------------------------------- johnathan · 2023-10-23 17:16 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 · 2023-10-23 18:54 Quote from: johnathan on October 23, 2023, 07:16:27 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 · 2023-10-24 09:01 Quote from: johnathan on October 23, 2023, 07:16:27 pmThanks 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). QuoteI 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 : QuoteThe version using CmdLine attempts to split the command line in a binary and separate command-line arguments. This version of the function is deprecated. QuoteMeanwhile 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. ---------------------------------------------------------------------- johnathan · 2023-10-30 22:06 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 ---------------------------------------------------------------------- TRon · 2023-10-31 18:35 Quote from: johnathan on October 30, 2023, 11:06:03 pmProgress: 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). QuoteTodo: 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. QuoteI 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)). ---------------------------------------------------------------------- johnathan · 2023-11-01 11:51 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 · 2023-11-03 20:48 Quote from: johnathan on November 01, 2023, 12:51:46 pmThe 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. QuoteI 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"). QuoteThanks 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. ---------------------------------------------------------------------- johnathan · 2023-11-30 12:17 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 · 2023-11-30 17:23 Quote from: johnathan on November 30, 2023, 01:17:57 pmAs 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. ---------------------------------------------------------------------- johnathan · 2023-12-02 15:46 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 · 2023-12-03 01:52 Quote from: johnathan on December 02, 2023, 04:46:02 pmAttached is the bash script that I use to produce the input for my Lazarus program. Something to work with... QuoteIt 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i oldnumber=""while IFS= read -r line ; do oldnumber=("$line")done < "$data2/music29.txt" echo "old batch number " $oldnumberechoecho enter batchread batchrunnumber=$batch 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program bashbash; {$mode objfpc}{$H+}{.$define mysetup} // for my personal setup not matching yours. // https://forum.lazarus.freepascal.org/index.php/topic,64932.0.html// https://wiki.freepascal.org/FindAllFiles uses  classes, process, fileutil, sysutils; const  {$ifdef mysetup}  source = './flacs';  {$else}  source = '/mnt/music/bashmusic/source1';  {$endif}  FindRecursive = false;  // search source directory recursively for flac files (true (=yes)/false (=no)). Your batch file doesn't.  procedure Print(s: string); overload;begin  {$ifdef mysetup}  writeln(s);  {$else}  // in case you wish to use lazarus and display the output to a memo  // then your code should be looking something like:  Form1.InfoMemo.Append(s);  {$endif}end; procedure Print(s: string; const args: array of const); overload;begin  print(Format(s, args));end;  procedure test;var  FileNames: TStringList;  Filename : string;   command  : string;  parameter: string;  rc_result: string;   Artist: string;  Title : string;  Album : string;begin  // create a stringlist that will contain the found filenames  FileNames := TStringList.Create;  try    // find all the files in directory source that matches the mask *.flac    FindAllFiles(Filenames, source, '*.flac', FindRecursive);    print('found %d files.', [FileNames.Count]);     // iterate through the FileNames list    // equivalent to your bash line: for filename in $source/*.flac ; do    for FileName in FileNames do    begin      print('');      print('handling filename %s', [Filename]);       // equivalent of your bash line: metaflac --show-tag=artist $filename    command   := 'metaflac';      parameter := '--show-tag=artist';      if RunCommand(command, [parameter, FileName], rc_result) then      begin        Artist := rc_result.TrimRight;      end      else print('error running command %s %s', [command, parameter]);       // equivalent of your bash line: metaflac --show-tag=title $filename    command   := 'metaflac';      parameter := '--show-tag=title';      if RunCommand(command, [parameter, FileName], rc_result) then      begin        Title := rc_result.TrimRight;      end      else print('error running command %s %s', [command, parameter]);       // equivalent of your bash line: metaflac --show-tag=album $filename      command   := 'metaflac';      parameter := '--show-tag=album';      if RunCommand(command, [parameter, FileName], rc_result) then      begin        Album := rc_result.TrimRight;      end      else print('error running command %s %s', [command, parameter]);       // show the resulting answers:      print('Filename = %s', [Filename]);      print('Artist   = %s', [Artist]);      print('Title    = %s', [Title]);      print('Album    = %s', [Album]);    end;   finally;    FileNames.Free;  end;end; begin  test;end.  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). ---------------------------------------------------------------------- johnathan · 2023-12-05 10:58 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