Reading image files from computer in a Java program via shell script - java

I have a Java program that reads an image file (.jpg, .bmp, .png )) and creates indices on that file using a clustering algorithm. But the problem is that every time I have to explicitly give the name of that image file, which is to be indexed. What I want is a code that will automatically scan all images present in my Linux system and index them. I found it's possible by shell script but still not getting it.

From what I understand, you want to execute an *.sh script through a java program which in turn loops over some files in a folder?
Have you tried something like this:
public void runCmd() throws IOException, InterruptedException {
String cmd = "/home_dir/./my_shell_script.sh";
Runtime run = Runtime.getRuntime();
Process pr = run.exec(cmd);
pr.waitFor();
}
This only gives a rough idea what you need to do, but you get the gist

You can use find, and pipe its output to your program:
find \( -name "*.jpg" -or -name "*.png" \) -printf "%h/%f\n" | java YourProgram
and read the filenames, including paths, from stdin (assuming none of them contains a newline character).
For the whole filesystem, you would start from the root dir:
find / ...
A better solution, and not too hard to implement, would be, to search the files in a platform neutral manner from your program, and giving it only a starting path. Here is a good solution, you only need to apply a filter for the file types (jpg, png, bmp).

Related

How to recursively call a Java program with PowerShell and pass in a file path

I am trying to batch rename files in a folder. For example, right now I want to remove the character at the second index in the names of all of the files in a given folder. I have written a Java program that will do this given the path of the file.
The problem is that I am trying to batch the process with PowerShell, and I have very little knowledge of PowerShell. I basically just started using it today, and mainly to test run my Java program from the command line. I decided to try PowerShell for this because I saw a YouTube video where someone used PowerShell recursively to remove a certain character (like a "-") from every spot it appears in every file name in a folder. I thought maybe I could recurse with PowerShell to batch the process of changing every file name.
I want to recursively call the Java program with PowerShell and have PowerShell pass in each path of each file one by one in a folder to the Java program. I don't know if this is possible, but I'm hoping it is.
I have tried the following, though since I don't really any knowledge of PowerShell, I don't really know what to try. "Copy" is the name of the folder in which the files I want to modify are located.
get-childitem -recurse | java -cp "C:\Users\Media PC\Documents\Renamer\src\main\java" org.example.Main $_.name
I am getting the Java program to run, because I'm getting an error back from the program saying I didn't pass in a proper file path.
Building on Abraham Zinala's helpful comment:
Leaving aside the fact that invoking an external program (i.e., creation of a child process) file by file is inefficient:
Get-ChildItem -File -Recurse | ForEach-Object {
java -cp "C:\Users\Media PC\Documents\Renamer\src\main\java" org.example.Main $_.FullName
}
Note: The -File switch limits results to just files (doesn't include directories).
PowerShell's automatic $_ variable can only be used inside script blocks ({ ... }), so using $_.name as an argument as-is won't work.
See this answer for all contexts in which $_ is meaningfully defined.
In order to pass an argument to a command that isn't designed to take its input directly from the pipeline, use the ForEach-Object cmdlet for custom-processing of each input object one at a time.
Inside the script block passed to it, you can use $_ to refer to the pipeline input object at hand.
Get-ChildItem outputs instances of the following .NET types:
System.IO.DirectoryInfo(for directories) and
System.IO.FileInfo (for files)
Their .FullName property contains their full, file-system-native path, so $_.FullName is a robust way to refer to just that. Given that .Name only reports the mere file name, it wouldn't be sufficient to identify the file at hand in a recursive traversal of the current dir.
In PowerShell (Core) 7+, you could use just $_, because there such instances consistently stringify as the value of their .FullName property (when passing arguments to an external program, objects are implicitly stringified) - unfortunately, this is not the case in Windows PowerShell; see this answer.

Java emulating the "open with" on a .bat file

I'm trying to automate an arduous process but I've run into a wall that I can't seem to google my way around.
This is the process that I'm trying to automate
The batch file contains:
cd %~dp0
"%~dp0raindrop.exe" -g om -i %1 -o "%~dp1
PAUSE
What I'm trying to do: Stream in from a folder a bunch of '.sm' files and pass them one by one through the bat file creating a Folder for the outputted file created from the .bat process.
Explaining what these set of commands do would be great as I would prefer to create one more fit for my purpose. Which is bulk converting and sorting, so the output directory assuming thats handled in that batch file would need to be understood.
What i've tried at the moment its just running the .bat as is
%1 is window-batch-ese for 'the first parameter'. That makes some sense, I hope.
%0 is window-batch-ese for 'the batch file itself'. If you think about it now knowing what %1 means, this does make a little bit of sense: It's the '0th parameter' - the one to the left of the first parameter, which is the batch file itself.
%~letters0 is a way to tell windows; I want %0, but, I want you to modify it. There are many letters. d in particular means 'drive letter', and p means path.
Thus,
%~dp0 is windows-batch-ese for 'the full path (including drive letter) to the directory where the batch file currently executing lives.
%~dp1 is windows-batch-ese for 'take param 1 and turn it into an absolute path, then give me the directory that contains this argument.
Thus, you should now be able to recreate what this batch script does in pure java:
It runs the file raindrop.exe, by asking windows to run that by providing the full, absolute path to that executable, which is located in the same place the batch file is located.
It then passes 6 arguments to it:
-g
-om
-i
the first parameter
-o
if the first parameter resolves to a file, then that file, turned into an absolute path, and then the directory (i.e. if passing 'foo.txt', and that is in C:\example\whatever\foo.txt, the last arg is C:\example\whatever).
Use ProcessBuilder and you can recreate this feature fully.
NB: Your batch script is probably broken; it's missing a closing quote. Also, the fact that %1 is not quoted means that any files with spaces in it will also break this batch script. I assume you have no need to replicate these bugs in the java take on this.
NB: Run raindrop.exe with ProcessBuilder. Forget the bat file, you don't want to run that.

java why not just executing 'xcopy /S $sourceDir/* $targetDir' or similar instead of 'reinventing the wheel'?

im still relatively new to java but i have experienve in scripting like DOS, Windows and Bash. today i would like to EASILY copy recursively the content of an directory (files and directories) from a sourceDir to a destinationDir from my Java CLI App.
i searched the net up and down and found PLENTY of "solutions" to this using Oracles and/or Apaches FileUtils etc. But they all require sort of "reinventing the wheel" and are 20+ Lines of code, handling each and every file and dir separately with great afford for something that on the command line shell is done by a SINGLE LINE.
For both on Windows and linux its usually no more than a simple...
cp -a "$sourceDir"/* "$targetDir" # on linux
or
xcopy /s /e %srcdir%\* %trgtdir% # on windows
Yet I was unable to find a prepared library or tool for java that does just that like xcopy/robocopy or cp on bash without adding my a whole new "copy" Class to my app :/ .
Is there a good reason why i should "re-invent the wheel" and no just do some sort of "external shell execution" to call one of those command line tools to have the job done within 2-3 Lines of Code?
Thanks for any Advice and Explanation.
Axel
Apache Commons I/O has a method that does this, you need to use the three-argument version of FileUtils.copyDirectory rather than the two-argument version (which copies the directory itself rather than its contents):
public static void copyDirectory(File srcDir, File destDir, boolean preserveFileDate)
throws IOException
This method copies the contents of the specified source directory to within the specified destination directory.
Here is a one statement Java solution:
Runtime.exec(new String[] {"sh", "-c",
"cp -a \"" + src + ""/* \"" + target + "\""});
Obviously not portable, but there is no reinvention of wheels here.
The trick is to let the shell handle the wildcard expansion for you.
I searched the net up and down and found PLENTY of "solutions" to this using Oracles and/or Apaches FileUtils etc. handling each and every file and dir separately with great afford for something that on the command line shell is done by a SINGLE LINE.
My initial thought is...
...........................................
Why you say ApacheCommons.FileUtils is 20+ lines of code??
copyDirectoryToDirectory(File srcDir, File destDir) API says :
Copies a directory to within another directory preserving the file dates.
This method copies the source directory and all its contents to a directory of the same name in the specified destination directory.
FileUtils.copyDirectoryToDirectory(new File(folder_source), new File(folder_destiny));
But they all require sort of "reinventing the wheel" and are 20+ Lines of code
Did you check how long is cp command source code?
Here it is: cp.c from www.gnu.org there are more than 1000 lines of code.

how to link ghost script in java to reduce the PDF size?

String[] cmd = {
"gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE -dQUIET -dBATCH -sOutputFile= C:\\Users\\342008\\Desktop\\t\\Pa_10_12.pdf C:\\Users\\342008\\Desktop\\t\\P1_10_12.pdf"
};
try {
Runtime.getRuntime().exec(cmd);
} catch (IOException e) {}
am trying to use ghost script to reduce the PDF file size with the help of command line argumenet, am getting IOexception for the above input string object cmd, could some one please help run this command to use ghostscript?
Firstly, while it is possible that running a PDF file through the pdfwrite device will make the file smaller, this is not the purpose of the device, and there are circumstances under which it will produce a bigger file.
If you really want to do this, then don't use the -dPDFSETTINGS switch. Instead set each parameter individually, take the time to read the documentation and see what they do so that you can make an informed choice.
You haven't said what operating system you are using, nor which version of Ghostscript, but I can see several possible problems:
1) The Ghostscript executable is not called 'gs' on all operating systems, possibly you are using the wrong name. The syntax of the parameters leads me to believe this is a Windows system, in which case the executable is called gswin32 (for the windowed version) or gswin32c (for the command line version).
2) You haven't specified a path to the executable. This will only work if the executable can be found on the OS' search path (usually the %PATH% environment variable)
Your command line apparently includes "-sOutputFile= C:\Users\342008\Desktop\t\Pa_10_12.pdf" You must NOT leave extraneous spaces in parameters. What you have written there will cause GS to assume an output file with an empty name, and then treat the filename as an input file for processing.
I would suggest that before you try this in Java you try running the command from the command line of your Operating System. If that doesn't work then it isn't going to work from Java either......

Replacing a line in a large number of java source files

I have around 600 java classes in a project with random names (there is no pattern in their names).
I want to replace a particular line from inside these classes with another line.
For e.g. line inside these files is
System.out.println("Product is: "+myProduct);
and I want to replace that line with
System.out.println("Object is: "+myObject);
The above line is just an example showing what I want to achieve.
I am using RAD 7.5 for development.
Is there a simple way to do this in all 600 files at once?
Yes. By opening the Search - File... dialog box, entering what you want to search for and the file filter you want, and then clicking Replace.
No. No access to UNIX system.
That's your first problem. Install Cygwin so you have a solid shell, and then you can learn how to do batch operations on source code. Being able to grep around easily can make it much easier to learn your way around large code-bases and narrow down the amount of code that is likely to contribute to a thorny problem.
Once you've got that installed, you can solve your immediate problem with
perl -i.bak \
-pe 's/System.out.println\("Product is: "+myProduct\);/System.out.println("Object is: "+myObject);/' \
file0.java file1.java ...
Breaking it down:
-i means treat the arguments as files to modify in-place
.bak means make a copy of the input files with the .bak extension before making changes
-p means wrap the program in a loop that grabs a line, runs the program, and prints the line
-e 's/.../.../' means the quoted part is the program to run, and it does a regular expression substitution.
the rest are the files to run it on.
Alternatively,
find . -name \*.java
should list all the java source files under the current directory.
Assuming that directory doesn't have spaces in its path, you can then do
find . -name \*.java | xargs perl -i.bak -pe 's/.../.../'
where the ... is the replacement above to run it over all Java sources under the working directory.

Categories

Resources