Using the various Java APIs I can implement the following shell commands in Java successfully: pwd, dir/ls, copy/cp, del/rm without invoking the shell itself to execute these command to for me.
E.g.,
case "pwd":
System.out.println(System.getProperty("user.dir"));
break;
case "dir":
case "ls":
File myDir = new File(System.getProperty("user.dir"));
String[] filesInDir = myDir.list();
for(String fn: filesInDir)
System.out.println(fn);
break;
The only basic command that is giving me trouble is "cd". Surely there must be an API function that would let me do this? However if there is I've missed it.
Note: I am not trying to execute anything external to the program, I simply want to be able to navigate the file system interactively for the duration of the program run and manipulate files in a very limited way via the API. In other words, this program emulates a very basic shell.
I've seen these question, but they haven't really helped, one states this is not possible, true?
How to change current directory in JAVA?
Changing the current working directory in Java?
Changing the current directory in Java to implement "cd" command in linux
Using Windows 7 with JDK 7.
There is no such api function but you can emulate it: store current directory in variable. During initialization assign this variable to System.getProperty("user.dir"). In all your methods use this variable. "cd" command should change this variable.
Related
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.
I am writing a java program dor Oracle EBS that needs to switch user because of specific permissions defined on an user different than applmgr.
The approach we're taking is to have a java class that will switch user on a separate session and then will list the file from a folder that the new user has access.
Any options available?
So far I could create two shell script files and then I run these shell scripts, one that will store environment variables and the other one will actually switch user and list the files.
Appreciate your help.
you could change the group permissions on the file. You could start a System.process( "su user && cat file" ); You could have the other user copy the file to you using a cronjob...
You can try having Java launch a local command on the system then as part of that command launch another program (far from being very clean, but probably would work)
Check out this Class file for examples on launching local commands:
https://github.com/SnakeDoc/RPi_SerialGPS/blob/master/src/com/vanomaly/rpi/serial/gps/util/System.java
You should be able to use setuid - I expect there is a version available directly in Java, but otherwise, it shouldn't be that hard to make your own JNI code to do that.
However, it may be simpler to run a command that switches user (using su or sudo, for example) and then runs the required Java code.
I am running Ubuntu 11.04.
I am trying to use a "C" execlp program to run a Java program, and then I want to setuid on the "C" program so the Java program can execute as root. There is an example of this here:
http://www.coderanch.com/t/110254/Linux-UNIX/setuid
I followed the example to the letter except instead of being the tomcat user, I used root.
Root is able to execute the "C" program which in turn executes the Java program. And, before giving root ownership, the User (me) can run the "C" program which executes the Java program. But once I setup to use setuid, and the User tries to execute the program. I get what seems to be an LD_LIBRARY_PATH type of error:
java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory
The libjli.so file exists under the Java JRE. Both the User and Root can see this file when they run individually. But the User cannot see it when he runs the program after setuid to root has taken place.
Is there some different way that root's LD_LIBRARY_PATH gets set when a setuid program executes? Is this an interactive vs. non-interactive problem?
Any ideas? Thanks in advance.
As the LD_* environment variables can be used to load code into a process, they are all ignored by setuid binaries. You will probably need to make the setuid binary a wrapper which executes the C program.
Setting the setuid bit on a file will change the process's effective UID but not the real UID. The dynamic linker will check to see if EUID ≠ RUID, and if so, it will ignore all environment variables. Your wrapper will have to filter the environment variables itself (important!) and once done, change the real UID to match the effective UID.
Warning: Don't forget to scrub the environment variables well, unless you are okay with giving everyone on the box full root access.
To work around the LD_* environment constraints on setuid programs, on most POSIX systems you should be able to do this within your wrapper code:
setreuid(0, 0);
which will set both the real and effective UIDs to be root, although this will only work if the program itself was started with the setuid bit enabled.
I wouldn't do it, though.
Look at why your Java program needs to run as root, and see if there are better ways to give it the privileges it needs without actually running as root.
I am trying to run a perl command with Java runtime exec in linux/ubuntu/gnome. The command generates an pdf file, but it saves it in my home folder. Is there any way that the exec method can set an output path for the commands executed? Thanks in advance.
The exec method just runs the command on the operating system, so you'll want to change the command you're running with exec more than anything in "Java" per se.
There are a few possibilities:
Change the working directory of your java program. The .pdf is being saved in your working directory because this is where the program is being run.
Unfortunately it's not simple to change this value after the program has been launched. It is, however, trivial to change before the program starts; just change the working directory before starting the program.
Move the file to it's desired location after it's been created in your home directory.
Change the command so that it includes the target location. Your perl script may have an option that will enable you to save it's output to a certain location (usually -o or --output). Using this your program would change from:
Runtime.exec("perl someprogram");
to something like:
Runtime.exec("perl someprogram -o /path/to/some.file")
You might be able to use "output redirection", if there is no option to do this.
Try something like what's below as your argument:
Runtime.exec("perl someprogram > /path/to/some.file")
Unfortunately, without knowing more details of your situation I can't provide more concrete advice.
While each approach has benefits and drawbacks, it's probably best to just implement the one that you understand best; if you can't get one to work, try another.
A good, free online resource for learning is Introduction to Linux: A Hands On Guide.
Section 2.2 has details on cd which you can use for 1..
Section 3.3, section 3 teaches about the mv command, which will be useful in 2..
Section 5.1 is about I/O redirection. Knowing about "output redirection" and the > operator, are important for 4..
For 3., you'll have to consult the documentation of the perl program you're using.
You could modify the Perl script to accept an absolute path for the output.
You can trying setting the working directory using exec(java.lang.String[], java.lang.String[], java.io.File) where File is the directory the command is executed from.
If all else fails, you'll can always copy the generated file from the Home directory to your final location.
I want to use system commands like mkdir and rmdir while running a java program.
How can I do that?
Why do you want to use the command line? FYI, there are built-in platform-independent File classes.
http://www.exampledepot.com/egs/java.io/deletefile.html
http://www.roseindia.net/java/beginners/java-create-directory.shtml
Make directory:
new File("dir path").mkdir();
Remove directory:
new File("dir path").delete();
'new File' here is a bit of a misnomer, it isn't actually creating the directory or a file. It's creating a Java resource hook which you can use to query or operate upon an existing filesystem resource, or create a new one at your request. Otherwise, use Runtime.getRuntime().exec("command line here") for using command line operations (not advised!!).
Edit: sorted out the problem the question poster was having:
String envp[] = new String[1];
envp[0] = "PATH=" + System.getProperty("java.library.path");
Runtime.getRuntime().exec("command line here", envp);
Note the insertion of envp into the exec(..) method call, which is basically the PATH variable from the environment.
As the other mentioned, you shouldn't do this for simple file management. But to have it mentioned: The Java API has a class called Runtime, that allows system calls... for example:
Runtime.getRuntime().exec("some_command");
The best is not to, but rather find the pure Java API function that does it. It is cleaner, easier to understand and much less error prone. It is also the only way to do Java that is write once run everywhere. Once you are calling shell commands, you are tied to that shell.
In your case you are looking for the java.io.File class, and specifically the mkdir and delete methods.
For reference of people stumbling onto this question and wondering why Runtime.getRuntime().exec("mkdir foo") doesn't work even when incorporating the environment as per Chris Dennett's answer, the most probable reason is that you don't have a program called "mkdir" on your system. While most Unix-like systems have a program of this name, it isn't absolutely necessary for them to have one, and Windows doesn't have one, because in both cases the shell interprets this command itself, rather than passing it to an external program.
To make it work, try ...exec ("cmd /c mkdir foo") for NT-family Windows (or "command /c mkdir foo" for Windows 95 family), or exec ("sh -c \"mkdir foo\"") for Unix.
The fact that there isn't a platform-independent way to do this is yet another reason to prefer the Java APIs for performing the task.
Hi Agree to the fact of not been platform independent but just for testing an app I had to use it.
The solution in my case for the
Runtime.getRuntime().exec("my_command_name") ;
for not working was i had to give the full path to where the batch/sh/executable file was
ie:
Runtime.getRuntime().exec("/d/temp/bin/mybatfile");