Print full path to file from terminal? - terminal

From the terminal lets say I navigate into a directory with a file that I'd like to "print the full path to including the file name with the spaces converted to \ \". Is there a command to do this from the terminal?
The two specific things I'm having trouble with are
printing out the full path with the spaces converted in \ \
printing out the full path including the file I'm interested in
Perhaps there are some flags that can be added to the "find" command?

See greadlink -f in coreutils as described by #tomyjwu in another post

Related

How to use gitbash with file names that contain ASCII exclamation point characters like !0-MyFolder

I need to use gitbash on MS-Windows with file folder names that contain an exclamation point as the first characters, like "!0-MyProjectFolder" (without the quotation marks. I use the exclamation point to sort Microsoft Windows files to the top, since Windows does not provide a way to index and force sort order of files and folders.
Gitbash keeps giving me error messages:
I've tried several syntaxes already:
$ cd "!0-Projects-WIP"
bash: !0: event not found
$ cd "\!0-Projects-WIP"
bash: \!0: event not found
$ cd !0-Projects-WIP
bash: !0: event not found
Be clear that I am NOT parsing a string like '/New.*desktop.*is/!d' in the StackOverflow posting at How to address error "bash: !d': event not found" in Bash command substitution
VNCServerAndDisplayNumber="$(echo "${VNCServerResponse}" \
| sed '/New.*desktop.*is/!d' | awk -F" desktop is " '{print $2}')"
I am passing the directory name !0-Projects-WIP to GitBash, so that I can change into the directory named !0-Projects-WIP. I am not intending to do double-quoting or history expansion. If the exclamation point in the folder name appears to be a history expansion directive, then that is not the intended result. The ! must be escaped in my case so that it is read correctly as part of the folder name, and the shell command "cd" interprets it as a string.
I realize now that !0-Projects-WIP is probably a bad name to a Unix shell parser because it directs the command line parser to do something that was not my intention, but for the MS-Windows command line shell there is no confusion.
I got it to work with just a single escape character in front of the string:
$ cd \!0-Projects-WIP
rlysa#domainname MINGW64 /c/users/rlysak01/desktop/!0-Projects-WIP (master)
$
Simple solution. No quotation marks needed on the folder name string.

How to create one output file for each file passed to a loop in bash?

I have a file that I pass to a bash command that will create an output in a loop like so:
for file in /file/list/*
do
command
done
I wish to save the output that would have gone to standard out of each loop to a text file in my working directory. Currently I am trying this:
for file in /file/list/*
do
command | tee "$file_command output.txt"
done
What I expect to see are new files created in my current directory titled file1.txt_commandoutput.txt, file2.txt_commandoutput.txt, etc. The output of the command should be saved as a different file for each file. However I get only one file created and it's called ".txt" and can't be opened by any standard software on Mac. I am new to bash scripting, so help would be much appreciated!
Thanks.
Your problem comes from the variable name you're using:
"$file_command_output.txt" looks for a variable named file_command_output (the dot cannot be in the variable name, but the alphanumerical characters and the underscore all can).
What you're looking for is "${file}_command_output.txt" to make the variable name more explicit.
You have two issues in your script.
First, the wrong parameter/variable is expanded (file_command instead of file) because it's followed by a character that can be interpreted as part of the name (the underscore, _). To fix it, enclose the parameter name in braces, like this: ${file}_command (see Shell Parameter Expansion in bash manual).
Second, even with fixed variable name expansion, the file won't be created in your working directory, because the file holds an absolute pathname (/file/list/name). To fix it, you'll have to strip the directory from the pathname. You can do that with either basename command, or even better with a modified shell parameter expansion that will strip the longest matching prefix, like this: ${file##*/} (again, see Shell Parameter Expansion, section on ${parameter##word}).
All put together, your script now looks like:
#!/bin/bash
for file in /file/list/*
do
command | tee "${file##*/}_command output.txt"
done
Also, to just save the command output to a file, without printing it in terminal, you can use a simple redirection, instead of tee, like this: command > "${file##*/}_com...".
If you are not aware of xargs, try this:
$ ls
file
$ cat > file
one
two
three
$ while read this; do touch $this; done < ./file
$ ls
file one three two

Deleting "C:\Blah\Blah\..\...\Blah" File on Unix

I have a remote Linode, which I am using Cygwin to access. An errant database file, specifically "C:\Users\Blah\Blah\website\blah\sqlite.db" was created. This file was used for local testing on my Windows machine, but was generated due to a mistake on the Linode. Note, this is the full file name inside the Linode, not the location of it. This is Windows syntax, not Unix, which is where I think the problem lies.
Now, I cannot delete it! It says, cannot remove file "file name" where file name does not have any of the original backslashes. This tells me that it cannot recognize that this is an errant windows DB file.
How can I delete this? If I had access to a GUI folder I could use that, but I only have the command line!
Please help!
The backslash and colon are not special characters to the filesystem (which is why you can have a file with those characters in its name), but backslash is a special character to the shell (and : is special in some contexts).
You just have to pass the file's name to the rm command. To do this from the shell, you need to escape the backslash characters.
This should work:
rm C:\\Users\\Blah\\Blah\\website\\blahsqlite.db
For example (I just tried this on my own system):
$ touch C:\\Users\\Blah\\Blah\\website\\blahsqlite.db
$ ls
C:\Users\Blah\Blah\website\blahsqlite.db
$ rm C:\\Users\\Blah\\Blah\\website\\blahsqlite.db
$
And if your shell supports tab completion, then you can probably just type rm Ctab
and, if there are no other files in the current directory whose names start with C, the shell will expand that to (an escaped version of) the file name. (Bash happens to insert a a \ in front of the : as well; this is unnecessary but harmless.)

Strange PATH behavior in win-bash

I installed win-bash on Windows 7 and I'm getting the following strange behavior.
bash$ cat C:/Home/.bashrc
PATH="C:/Program\ Files/GnuWin32/bin:C:/Windows/system32"
bash$ . C:/Home/.bashrc
bash$ echo $PATH
C:/Program\ Files/GnuWin32/bin:C:/Windows/system32
bash$ which diff
which: no diff in (.;C;\Program\ Files\GnuWin32\bin;C:\Windows\system32)
bash$ which ls
which: no ls in (.;C;\Program\ Files\GnuWin32\bin;C:\Windows\system32)
Why are the PATH values different?
The PATH value returned by which contains .:C;\Program\ Files\GnuWin32\bin
Note:
the ".:" in the beginning that does not exist in the bash PATH value.
the "C;" (not C:) contains a semi-colon instead of a colon.
the which PATH value has back slashes (\\) instead of forward slashes (/)
Where is which sourcing these PATH values?
I can not find any other .bashrc or .profile or profile files anywhere on the machine.
In addition,
bash$ diff file-abc.txt file-xyz.txt
1c1
< abc
---
\> xyz
bash$ ls file-abc.txt
file-abc.txt
Both diff and ls work on the command line even though which can not find the diff or ls commands.
Both diff and ls are located in C:/Program\ Files/GnuWin32/bin
But which returns C;\Program\ Files\GnuWin32\bin (note C; not C:) which is why which can not find ls or diff.
Again, where is which sourcing these PATH values?
In my bash script named Try1.sh I have these lines.
\`diff $CURRENT_FILE $NEW_FILE\`
\`ls $CURRENT_FILE\`
The diff command fails with
Try1.sh: 21c21: command not found
The ls command succeeds. Why?
Both diff and ls live in the same PATH location C:/Program\ Files/GnuWin32/bin.
Windows has a different search algorithm to UNIX-like systems. On Windows the first directory to be searched is the directory which the parent program (.exe) was loaded from, then the current directory, then C:/Windows/system32 is searched. That's where the directory names are coming from.
The path environment variable is only used as a last resort!
For a full discussion on this, see MSDN entry for CreateProcess
which is also showing the Windows path directory separator as ;, rather than : which UNIX-like systems use. Also, / or \ are valid as a directory separator in a Windows path, but only / is valid on UNIX.
Also note that environment variables (like path) are not case sensitive on Windows, but on UNIX they are.
EDIT: I have been trying to track down the source code for win-bash but can't find it. I found some source code for which in GNUUtils, but can't be sure that it is the same version as you are using. The version I looked at, 2.4, makes assumptions about Windows which are not necessarily correct.
After downloading the binary for win-bash, I found that the bundled which is indeed version 2.4, and looks the same as the source code I have been looking at.
It is a separate program and not integrated with the rest of the shell code. To answer the question on directory separators and path separators, they are hard-coded for Windows (sys.h):
#define DIRSEP '\\'
#define PATHSEP ';'
The path is read from the environment variable using getenv.
Further edit:
The command
\`diff $CURRENT_FILE $NEW_FILE\`
is invalid. It is capturing the output from diff and then trying to execute it. 21c21 is the output from diff, and of course there is no such program as 21c21. Just use:
diff $CURRENT_FILE $NEW_FILE

command substitution but without breaking output into multiple arguments

Is there a way to do command substitution in BASH shell without breaking output into multiple arguments?
I copy the path of some directory (from the location bar in a GUI file browser) to clipboard and then issue the following command, where the command xsel returns the clipboard content, which is the path of the directory in this case:
cd `xsel`
But some path contain spaces or may even contain some special characters used by BASH.
How can I pass the output of a command as a single argument and without BASH messing with special characters?
cd "$(xsel)"
seems to handle all special characters (including $ and spaces).
My test string was boo*;cd.*($\: $_
$ mkdir "$(xsel)"
$ ls
boo*;cd.*($\: $_
$ file boo\*\;cd.\*\(\$\\\:\ \$_/
boo*;cd.*($\: $_/: directory
$ cd "$(xsel)"
$ pwd
/tmp/boo*;cd.*($\: $_
Have you tried:
cd "`xsel`"
That should do the job, unless you have dollars($) or back-slashes (\) in your path.
If you aren't doing this programmatically, most terminals in Linux let you paste from the clipboard with a middle-click on your mouse. Of course, you'll still need to put quotes before and after your paste, like #dave suggests.

Resources