Explicitly setting the current directory (pipeline shell) - pwd

SHORT: How do I explicitly set the current working directory?
LONG: So I have 52 programs daisy chained together. I have a shell script pipeline that works great. Only problem is I can only run it if I cd into the directory with the files and run it. Some of the sub-programs do not have a mechanism that allows me to explicitly set output directories. They dump everything into the current working directory. This is fine if you are running 1 instance of this pipeline, but not so great if you are trying to process a dozen data-sets one after another. I know I can get the current working directory with:
echo $PWD
But how do I set it?

You can set the current dirctory for individual programs in your pipeline without affecting the other program in your pipeline like this:
PWD=path1 command1 && PWD=path2 command2
In general, you can set any environment variable using that syntax. Here is a real example I tried in bash:
$ PWD=/home ./test.rb && PWD=/ ./test.rb
Running in /home
Running in /

Related

Why won't a Batch file start in the directory it was executed in?

I am programming a DOS-like shell, but it starts in %UserProfile% instead of %UserProfile%\Desktop\Coding projects\CM-DOS.
The actual shell, kernel.bat's code is:
#echo off
type INFO.txt
pause
INFO.txt is in the same directory as kernel.bat (CM-DOS).
It says:
CM-DOS is a FREE, open-source Disk Operating System by Tristan
Carpenter. If anyone trys to sell you a paid copy of CM-DOS, send me
an e-mail at tristan4#mail.com. Please use this DOS shell kindly. This
shell is licensed under the MIT License. Do whatever you want with the
shell, create closed-source versions, fork it, I don't really care.
The script tries to type "%UserProfile%\INFO.txt", which doesn't exist.
How can I start the file in it's actual directory, instead of %UserProfile%.
If you run the script (clicking or navigating (cd <folder>) and .\kernel.bat) and the current folder isn't, well, the current folder, then something is off with either your console setup or there is an additional code executed in the background. Try to echo %CD% to see what the folder is and check the prompt string usually in the shape of:
C:\Users\Username>
which is the default path if you run cmd.exe as a user or:
C:\Windows\System32>
if you run as an Administrator / user with elevated privileges.
This can be changed though with regedit.exe.
However what you might be seeing is that you run your code (kernel.bat or however you name it) which might display the first path before execution or after the last command you might be dropped into a shell. Neither should be the case according to the code, yet it can happen if you started cmd.exe, then wrote cmd.exe (i.e. spawned another shell) and then ran your script.
What I suspect is that you're running the code like this:
C:\Users\You> .\Desktop\Coding projects\CM-DOS\kernel.bat
in which case the %CD% would be C:\Users\You and type command would be looking for C:\Users\You\INFO.txt. A better solution is simply creating a variable for the folder where your script is located - which is provided automatically, it's %~dp0 (echo %~dp0) and with that you can do:
echo off
type "%~dp0INFO.txt"
pause
to make it location independent, or better said, to access relatively according to the kernel.bat (the current script)'s location.
You can add cd %CD% and %CD% stands for the current direction. the final code would be
#echo off
cd %CD%
type INFO.txt
pause

How can I run ROS commands through a C based system() call?

I have this c based program to do some benchmarking and whatnot which I use heavily. I am a ROS noob, just starting to delve into ROS code to do some analysis.
Currently, I need to be able to call ros based commands (i.e. rosbag play, roscore, etc) through the system() function.
For those who do not know how it works, it basically just executes the command (i.e. system("ls"); system("./testScript.sh").
Right now I have a bash script set up to essentially run several small things including ROS commands. Executing the script works perfectly, but executing it through system always give me an error regarding ROS_cmd: Not found.
For example:
#/bin/bash
ls
echo hi
rosbag play rotating_detergent_1_6.bag
Gives me output error of : rosbag: not found - all the while executing the ls and echo
This happens independent of the ROS based command.
Any one know what is wrong?
edit: So to add, the C program is called in sudo. I noticed that the problem seems to be that system() executing in sudo does not have the appropriate ROS PATH.
For example:
echo $PATH -> /opt/ros/melodic/bin : rest
sudo su; echo $PATH -> rest
How should I go about properly addressing this?
ROS environment is a bunch of variables:
ROS_DISTRO
ROS_ETC_DIR
ROS_PACKAGE_PATH
ROS_PYTHON_VERSION
ROS_VERSION
ROS_ROOT
ROS_MASTER_URI
ROSLISP_PACKAGE_DIRECTORIES
Unless you want to set them all by yourself, you can use a very convenient uitlity script provided by ROS. The script is usually at /opt/ros/<ros_distro>/setup.bash
Just source the script in the terminal where you run your C program and then run your program.
source /opt/ros/<ros_distro>/setup.bash
You should not need sudo but in case you do , use it with -E flag to preserve the environment.

Why is atprogram not working from within a batch file?

I am working with an embedded system developed specifically for the company I work at. I want to use Atmel's command prompt to program the target processor which is pretty easy.
But, in the future, the technician building our products will do it themselves so I thought of a batch file they could run with the scrips for programming and checking the code for them automatically.
Here is the problem, I don't manage to get it running trough the *.bat file.
When I do it without I just start the Atmel console and type
atprogram -i ...
I have tried writing the batch file like:
"C:\...\StudioCommandPrompt.exe" atprogram -i ...
Which gives me the result atprogram is neither a file nor a program
I also tried with:
START "C:\...\StudioCommandPrompt.exe" atprogram -i ...
Then the program starts in a separate prompt, and produces the same error as above.
The empty set as suggested in the comments:
START "" "C:\...\StudioCommandPrompt.exe" atprogram -i ...
Gives the same result as without the empty set.
Does anyone know how to resolve this?
SOLUTION:
START "programTool" /B /WAIT "C:\...\atprogram.exe" -i ...
I.E. refering to the correct software (cred: http://www.avrfreaks.net/forum/just-run-programmer hobbss)

Starting a process from a batch file with my user permissions

I have written some batch files in windows to centralise some calls to other batch files so that I can start up some processes easily, but when run from my central file the processes don't run properly; they need network access and this seems to be denied and I get a load of connection refused exceptions. This is presumably a permissions problem, but I'm not sure how to get round it. I've tried running my script by ricght clicking and choosing 'run as administrator' but this doesn't work properly (my first 'cd...' does not change the directory for some reason, then the calls fail)
Is there a way I can imply my permissions to the other processes?
My scripts look basically like this:
cd "F:\Applications\Process1"
START "Process 1" runProcess1.cmd
cd "C:\Applications\Process2"
START "Process 2" runProcess2.cmd
command runas with option /savecred should ask for password the first time it runs.
maybe this can help http://www.bellamyjc.org/en/superexec.html,
It turns out if you try and use 'cd "F:\Applications\Process1"' drive F will switch to the chosen folder, but you won't be switched to drive F. i.e. you will still be at C:\user\username (or whatever the default is) and if you then type 'F:', you will be at 'F:\Applications\Process1'. This meant that I was running two instances of the same process from the same place, when in fact I wanted to run two instances of the same process in different locations, so it looked like ti was launching properly then faailing to get network permissions, but was infact conflicting with itself. To fix this, I chagned my script as so:
F:
cd "F:\Applications\Process1"
START "Process 1" runProcess1.cmd
C:
cd "C:\Applications\Process2"
START "Process 2" runProcess2.cmd
Meant as a comment on answered Aug 24 '12 at 14:18 user1111284
But I cannot comment until I get 50 Reputation.
Use "cd/?" to get the short summary of cd command usage.
Use "cd/d" to change the current drive as well as the path.
Change your script like this:
cd/d "F:\Applications\Process1"
START "Process 1" runProcess1.cmd
cd/d "C:\Applications\Process2"
START "Process 2" runProcess2.cmd
I post this to other seekers. The /d option should be better known.

Matlab 'exist' returns 0 for a file that definitely exists!

I'm running Matlab 7.8.0 under Windows.
I am calling an external utility using dos() which creates a file in the current directory.
I the file is created correctly, but it cannot be seen by exist or fopen, which return 0 and -1 respectively. The filename is correct!
>> pwd
ans =
I:\
>> ls
file1.asc file2.asc file3.asc
>> exist('file1.asc') % this file was there before
ans =
2
>> exist('file2.asc') % this file is newly created
ans =
0
to confirm it's not an odd/problematic filename, I checked from a Cygwin shell:
/cygdrive/i/ $ if [ -f file2.asc ]; then echo "OK"; fi
OK
So the file is good. I tried renaming it
/cygdrive/i/ $ mv file2.asc test
and in Matlab
>> ls
file1.asc file3.asc test
>> exist('test')
ans =
0
If I exit and restart Matlab it works fine. But I need to dynamically create the file and then access it!
Very mysterious.
You could try:
The rehash command to see if that helps.
The two-argument version of exists: exist('foo.txt', 'file')
The Matlab exist() command is not a simple filesystem operation; it also looks at variables, functions, etc. Since you're on I:, I'm assuming that's a network drive, and you're probably running in to the dir contents caching problem that Jonas mentions.
Here are a couple other workarounds, in case nsanders' two-arg exist() or Jonas' change notification fixes don't work for you.
Try using absolute paths to the files, like "fopen('I:\file2.asc')", instead of relative paths and pwd. Matlab will treat unqualified filenames as "partial paths" for both exist() and fopen(), and that interacts with the directory info caching. Ls() does not work with partial paths, which may be why it can see the file and the other functions can't.
You can use Java from within Matlab to do a simpler file existence test.
java.io.File('file2.asc').exists()
Or since the ls() command is showing the file you want, you can just implement the file existence check on top of ls.
ismember({'file2.asc'}, ls())
The "{ }" is necessary to make ismember() operate at the string level instead of the char level.
If you're still having trouble reading it, try doing a lower level read with Java from within Matlab. That will tell you whether it's specifically Matlab's I/O functions that are having trouble, or of the process itself lacks access to the file. Try this. If you get a char out of it, that means your Matlab.exe process can see the file.
istr = java.io.FileInputStream('file2.asc')
c = char(istr.read())
On Windows, I used to get change handle notification warnings at startup until I turned the warnings off. I don't have 7.8 at hand right now, but the warning may be off by default.
As explained on the MathWorks site, if Windows runs out of change notification handles, it will not be able to properly "sense" whether the content of a directory has changed, which might be causing your problems.
Are you sure that MATLAB is running as the same user as explorer is? If MATLAB requires elevated permissions to run then the drive mappings may be different and you could find that the I:\ drive is not mapped.
To fix this you would need to somehow map the I: drive under elevated permissions.

Resources