Is it possible in bash while typing a shell command to have a characters that fires an user defined program?
For example, the user types at shell prompt
cp
and then types a special character that fires a program allowing to navigate the file system to find the copy command source file.
The programs return the selected file name that is appended to shell cp command.
Now the user types again the special character that fires the same program as above to navigate the file system for finding the destination file or folder.
At this point the command is ready to be sent to bash for execution
Related
For both file associations, .py and .pl, I have a pair of ftype and assoc so that I can run Perl and Python scripts without explicitely specifying the path to their respective interpreter executable, like so:
C:\users\rene> .\abc.pl
C:\users\rene> .\xyz.py
When I do the "same" in a PowerShell console, executing the Perl Script opens another console in which it executes, yet the Python script executes in the same console.
Because the Perl Script runs in another console, I am faced with two problems: 1) I cannot redirect STDOUT of the script and 2) the console closes when the script is done, thus I cannot see its output.
I have no idea why the Python script behaves differently from the Perl script and I wonder what I need to change in order for the Perl script to run in the same console when executed in PowerShell.
Assuming that the .pl filename extension is associated with a file type that uses a console application to perform the Open verb on that file type (run ($fileTypeName = cmd /c assoc .pl) to learn the file-type name, then cmd /c ftype $fileTypeName to see its definition):
In order for PowerShell to run files with a given filename extension in the current console window, synchronously (assuming they're associated with a console application), that extension must be listed in the system-defined $env:PATHEXT environment variable, which is surprising.[1]
You can add .pl to $env:PATHEXT as follows:
For the current session only:
$env:PATHEXT += ';.pl'
Persistently:
Must be run from an elevated session (run as admin), and requires starting a new session to take effect:
[Environment]::SetEnvironmentVariable('PATHEXT',
([Environment]::GetEnvironmentVariable('PATHEXT', 'Machine') + ';.pl'),
'Machine'
)
Note: It is possible - though rare and not advisable - for a persistent user-level definition of this environment variable to shadow the machine-level (all-users) definition. If that is true for your user account, replace 'Machine' with 'User' above.
[1] As you state, the purpose of the $env:PATHEXT environment variable is to list filename extensions that are implicitly executable, so that, with .pl present in the variable, excecuting .\abc.pl can be shortened to .\abc. This aspect is conceptually separate from the file-type associations that allow defining what executable to pass non-executables with given filename extensions to on direct invocation, and it is arguably a bug that PowerShell couples these two aspects; it would make more sense for PowerShell to always run console-based executables in the current window, synchronously.
After I drag-and-drop a file, say from Finder, to say, Terminal running macos bash, is that value still accessible somewhere via a keyboard binding or an environment variable or some function or command? I know I could kill and yank the command line after the drag-and-drop lands on the command line, but I'd like something more direct if possible.
If you drag a file from Finder to the terminal the file name along with its path is displayed on the command line. It is not stored in any variable unless you write a code or script to read the file path and name. If you hit return after the name prints on the command line you'll probably get a "Permission denied" message (unless the name is an executable) but the path and file name will then appear in the history of commands. Typing history on the command line will show you the command you attempted to run. While not stored in a variable you should have temporary access to the info thru history.
In Windows, you can initiate a Bluetooth transfer of a file by right clicking the file and choosing Send to > Bluetooth device. The Bluetooth File Transfer box appears, after which you select what device to send to. I have found that I can achieve the same effect by dragging-and-dropping the file that you want to send onto C:\Windows\system32\fsquirt.exe.
To figure out how Windows passes files to programs when you use Send to or drag-and-drop, I wrote the following Python script and placed a shortcut to it in C:\Users\<username>\AppData\Roaming\Microsoft\Windows\SendTo. The shortcut's Start In directory is the .py file's containing directory. (I am using Python 3.6.)
#!python3
import os, sys
print(os.getcwd())
print(sys.argv)
input("Press Enter to exit...")
When I drag-and-drop a file onto the shortcut or the script itself and when I right-click a file and choose Send to > the new shortcut, the same thing happens in all three cases: on the first line, Python prints out the containing directory of the .py file, and on the second line, Python prints out a repr of a list containing two elements: the absolute path to the .py file and the absolute path of the file that I chose.
I wrote the following batch file for testing:
cd C:\folder\of\py\file\
C:\folder\of\py\file\argv_dump.py "C:\path\to\a\file.txt"
When I run this batch file, either from the command prompt or by double-clicking it in Windows Explorer, I get the same output from before. on the first line, Python prints out the containing directory of the .py file, and on the second line, Python prints out a repr of a list containing two elements: the absolute path to the .py file and C:\path\to\a\file.txt.
Now, I am trying to initiate a Bluetooth transfer on Windows 10 from a script. I have written a three-line batch file for testing:
cd C:\Windows\system32\
C:\Windows\system32\fsquirt.exe "C:\path\to\a\file.txt"
pause
This does not appear to send "C:\path\to\a\file.txt" to fsquirt.exe. The Bluetooth File Transfer dialog box appears, but it still asks me to choose what file I want to send. Running these commands in a command prompt window yields the same result.
How does fsquirt.exe know the difference between when I drag-and-drop or use Send to and when I manually pass it an absolute file path from a batch file or the command prompt? How can I get fsquirt.exe to notice the file path that I am giving it?
I did look at this other question, which suggested checking the current working directory of the batch file. Wouldn't cding inside my batch file take care of that, though?
In the past, I have used the Bluetooth Command Line Tools via Bluetooth Installer. They allowed me to automate a Bluetooth workflow via the Windows command line.
I run a batch file as an external tool (by adding it in Tools->External tools) in VS2010 (I've checked the "Use Output Window" option). This batch file performs compilation as in VS command prompt. The project that I'm working on has makefiles for various folders, so I use the mk command to build.
In the batch file, I set up the VS environment and then run the following commands:
cd $directoryWhichContainsFileToBuild
mk
cd main //This directory contains the executable that is to be built
mk
I see the output of the first mk in the Output window but after that it just hangs. I also tried to use an echo after the first mk but even that doesn't get printed in the output window (the ones before it can be seen).
Somewhere I read that there is an issue with VS 2010 output window where it hangs after showing some output, although I couldn't really be sure that that is what's the issue here.
Do I need to enable some other VS setting? Has anybody else encountered this issue?
Thanks.
Update: I unchecked the "Use Output Window" and "Close on exit" option, and I see an extra statement: "Press any key to continue". On doing that however, their is no further processing of the batch file.
Update2: Got it to work by prefixing mk with "call".
Thanks all who tried.
It is always good in batch files to specify executables with full path and file extension instead of just the file name. This avoids often lots of problems.
Here was just mk used instead of mk.bat. Therefore on every compile the command line processor cmd.exe searches for mk.* and then checks if any of the found files have an extension listed in environment variable PATHEXT. The order of file extensions separated by a semicolon in PATHEXT defines the order of execution in case of a directory contains multiple mk.* files.
If a command being specified in a batch file not being an internal command of cmd.exe without path, command line processor searches first for a file with given name in current working directory. This is often one more cause of error. What is the current working directory on execution of the batch file?
Next if no file to execute can be found in current working directory, the command line processor searches in all folders being listed in environment variable PATH separated by semicolons.
So specifying in batch files edited only rarely an external application or another batch file with full path, file name and file extension, in double quotes if necessary because of 1 or more spaces in path or file name, helps command line processor to more quickly execute that application or batch file and avoids problems because of executable not found (unknown command).
Sure, when typing commands in a command prompt window, nobody wants to enter the executables with full path, name and extension. But for batch files it is always good to be not lazy and type files to be executed with full path and extension.
TripeHound has given already the explanation why the observed behavior occurred here.
If a batch file is executed from another batch file without using command call, the command line processor continues batch execution in the other batch file and does never come back. In a C/C++ program this is like using goto with the difference that parameters can be passed to the batch file containing the further commands to be executed next.
But running from within a batch file another batch file with call results in continuation of execution below the line calling the other batch file once the other batch file reaches end, except command exit is used in the called batch file without parameter /B.
So the solution here is using:
cd /D "Directory\Which\Contains\File\To\Build"
call "Path\Containing\Batch\File\To\Build\mk.bat"
rem With mk.bat not changing current working directory change working
rem directory to the directory containing the executable to be built.
cd main
call "Path\Containing\Batch\File\To\Build\mk.bat"
BTW: exit exits command processor, exit /B exits just current batch file. I'll give you three guesses why the parameter is B and not a different letter. Yes, B is the first letter of batch.
Writing as a separate answer instead of an update in the question itself as many readers see the header and skim to the answer: got it to work by prefixing mk with "call". (#TripleHound has also posted the conceptual reason for it in the comment above.)
I'm working on a project that creates Windows shortcuts to batch files, and have been testing special characters in the pathname to the batch script. One problem that has me stumped is that a pathname will work when the shortcut is invoked normally, but if "Run as Administrator" is used, it does not work.
For example, if the pathname to the shortcut is "C:\Program Files\myapp )]}##$_-=+'.{[(\bin\hello.bat", I can run it fine when I click on the shortcut. When I select "Run as Administrator" it does not work. The shortcut Target value does have double quotes around the pathname.
I can invoke the above pathname with no problems from the Command Prompt, either running as Administrator or as a regular user.
I put in a prompt at the beginning of the batch script to determine if the batch script itself fails, but it does not. When run-as is used, it appears the script is never launched.
My guess there is something in how Windows (7) performs the run-as operation that is getting tripped up by one (or more) of the special characters in the pathname. Is there any known/documented pathname characters limitations of using run-as (with batch scripts[?])?
UPDATE:
After some testing, I discovered that it is the '#' character that screws things up. When I run a test with that character not present, the run-as operation succeeds. Not sure what is special about that character wrt run-as.
On my Windows 10, if a .cmd file's name contains # or ^ or & , the file cannot be run as an administrator. If a .cmd file's parent folder's name contains # or ^ or & , the file cannot be run as an administrator even if the file's name does not contain # or ^ or &.
Ironically, if a .cmd file's name is:
ππγ£γββ₯β
βΊγ₯β€οΈπ©
the file can be run as an administrator.