I am currently looking at this project (Mattermost) that has a certain line in the makefile that I'm confused about:
$(GO) run $(GOFLAGS) $(GO_LINKER_FLAGS) ./cmd/platform/*.go --disableconfigwatch &
What is the meaning of ./cmd/platform/*.go? What specific files are executed? The program executes correctly when I type it in the terminal.
I am trying to enter the command line arguments in an IDE but I need a specific entry file.....
Wikipedia
glob (programming)
In computer programming, in particular in a Unix-like environment,
glob patterns specify sets of filenames with wildcard characters. For
example, the Unix command mv *.txt textfiles/ moves (mv) all files
with names ending in .txt from the current directory to the directory
textfiles. Here, * is a wildcard standing for "any string of
characters" and *.txt is a glob pattern. The other common wildcard is
the question mark (?), which stands for one character.
Clearly, ./cmd/platform/*.go, starting in the current directory, looks in the cmd/platform directory for files matching the wildcard *.go.
The ls ./cmd/platform/*.go command will list the files on Linux.
So, the go run ./cmd/platform/*.go command compiles and runs these Go (*.go) source files. See Command go documentation: Compile and run Go program.
Related
When running scripts in bash, I have to write ./ in the beginning:
$ ./manage.py syncdb
If I don't, I get an error message:
$ manage.py syncdb
-bash: manage.py: command not found
What is the reason for this? I thought . is an alias for current folder, and therefore these two calls should be equivalent.
I also don't understand why I don't need ./ when running applications, such as:
user:/home/user$ cd /usr/bin
user:/usr/bin$ git
(which runs without ./)
Because on Unix, usually, the current directory is not in $PATH.
When you type a command the shell looks up a list of directories, as specified by the PATH variable. The current directory is not in that list.
The reason for not having the current directory on that list is security.
Let's say you're root and go into another user's directory and type sl instead of ls. If the current directory is in PATH, the shell will try to execute the sl program in that directory (since there is no other sl program). That sl program might be malicious.
It works with ./ because POSIX specifies that a command name that contain a / will be used as a filename directly, suppressing a search in $PATH. You could have used full path for the exact same effect, but ./ is shorter and easier to write.
EDIT
That sl part was just an example. The directories in PATH are searched sequentially and when a match is made that program is executed. So, depending on how PATH looks, typing a normal command may or may not be enough to run the program in the current directory.
When bash interprets the command line, it looks for commands in locations described in the environment variable $PATH. To see it type:
echo $PATH
You will have some paths separated by colons. As you will see the current path . is usually not in $PATH. So Bash cannot find your command if it is in the current directory. You can change it by having:
PATH=$PATH:.
This line adds the current directory in $PATH so you can do:
manage.py syncdb
It is not recommended as it has security issue, plus you can have weird behaviours, as . varies upon the directory you are in :)
Avoid:
PATH=.:$PATH
As you can “mask” some standard command and open the door to security breach :)
Just my two cents.
Your script, when in your home directory will not be found when the shell looks at the $PATH environment variable to find your script.
The ./ says 'look in the current directory for my script rather than looking at all the directories specified in $PATH'.
When you include the '.' you are essentially giving the "full path" to the executable bash script, so your shell does not need to check your PATH variable. Without the '.' your shell will look in your PATH variable (which you can see by running echo $PATH to see if the command you typed lives in any of the folders on your PATH. If it doesn't (as is the case with manage.py) it says it can't find the file. It is considered bad practice to include the current directory on your PATH, which is explained reasonably well here: http://www.faqs.org/faqs/unix-faq/faq/part2/section-13.html
On *nix, unlike Windows, the current directory is usually not in your $PATH variable. So the current directory is not searched when executing commands. You don't need ./ for running applications because these applications are in your $PATH; most likely they are in /bin or /usr/bin.
This question already has some awesome answers, but I wanted to add that, if your executable is on the PATH, and you get very different outputs when you run
./executable
to the ones you get if you run
executable
(let's say you run into error messages with the one and not the other), then the problem could be that you have two different versions of the executable on your machine: one on the path, and the other not.
Check this by running
which executable
and
whereis executable
It fixed my issues...I had three versions of the executable, only one of which was compiled correctly for the environment.
Rationale for the / POSIX PATH rule
The rule was mentioned at: Why do you need ./ (dot-slash) before executable or script name to run it in bash? but I would like to explain why I think that is a good design in more detail.
First, an explicit full version of the rule is:
if the path contains / (e.g. ./someprog, /bin/someprog, ./bin/someprog): CWD is used and PATH isn't
if the path does not contain / (e.g. someprog): PATH is used and CWD isn't
Now, suppose that running:
someprog
would search:
relative to CWD first
relative to PATH after
Then, if you wanted to run /bin/someprog from your distro, and you did:
someprog
it would sometimes work, but others it would fail, because you might be in a directory that contains another unrelated someprog program.
Therefore, you would soon learn that this is not reliable, and you would end up always using absolute paths when you want to use PATH, therefore defeating the purpose of PATH.
This is also why having relative paths in your PATH is a really bad idea. I'm looking at you, node_modules/bin.
Conversely, suppose that running:
./someprog
Would search:
relative to PATH first
relative to CWD after
Then, if you just downloaded a script someprog from a git repository and wanted to run it from CWD, you would never be sure that this is the actual program that would run, because maybe your distro has a:
/bin/someprog
which is in you PATH from some package you installed after drinking too much after Christmas last year.
Therefore, once again, you would be forced to always run local scripts relative to CWD with full paths to know what you are running:
"$(pwd)/someprog"
which would be extremely annoying as well.
Another rule that you might be tempted to come up with would be:
relative paths use only PATH, absolute paths only CWD
but once again this forces users to always use absolute paths for non-PATH scripts with "$(pwd)/someprog".
The / path search rule offers a simple to remember solution to the about problem:
slash: don't use PATH
no slash: only use PATH
which makes it super easy to always know what you are running, by relying on the fact that files in the current directory can be expressed either as ./somefile or somefile, and so it gives special meaning to one of them.
Sometimes, is slightly annoying that you cannot search for some/prog relative to PATH, but I don't see a saner solution to this.
When the script is not in the Path its required to do so. For more info read http://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_01.html
All has great answer on the question, and yes this is only applicable when running it on the current directory not unless you include the absolute path. See my samples below.
Also, the (dot-slash) made sense to me when I've the command on the child folder tmp2 (/tmp/tmp2) and it uses (double dot-slash).
SAMPLE:
[fifiip-172-31-17-12 tmp]$ ./StackO.sh
Hello Stack Overflow
[fifi#ip-172-31-17-12 tmp]$ /tmp/StackO.sh
Hello Stack Overflow
[fifi#ip-172-31-17-12 tmp]$ mkdir tmp2
[fifi#ip-172-31-17-12 tmp]$ cd tmp2/
[fifi#ip-172-31-17-12 tmp2]$ ../StackO.sh
Hello Stack Overflow
I want to move a couple of files from point a to point b
but I have to manually specify
mv /full/path/from/a /full/path/to/b
but some times there are 20 files which I have to move manually. Instead of /full/path/form/a, can't I just enter the a function which returns all the files which I want to move in my case;
/full/path/to/b is a directory, it's the target directory which all the files with extenstions mp3, exe and mp4 must go to:
mv ls *.{mp3,exe,mp4} /full/path/to/b
If I have to move a couple of files and I don't want to do it one by one, how can I optimize the problem?
The command mv ls *.{mp3,exe,mp4} /full/path/to/b in your question is not correct.
As pointed out in comments by #janos, the correct command is
mv *.{mp3,exe,mp4} /full/path/to/b
mv can complain about missing file if the file is really missing and/or the path is not accessible or is not valid.
As i can understand by your question description, if you go manually to the source path you can move the file to the desired directory.
Thus it seems that path is valid, and file exists.
In order mv to keeps complaining about *.mp3 not found (having a valid path and file) the only reason that pops up in my head is the Bash Pathname Expansion feature (enabled by default in my Debian).
Maybe for some reason this pathname expansion bash feature is disabled in your machine.
Try to enable this feature using command bellow and provide the correct command to mv and you should be fine.
$ set +f
PS: Check man bash about pathname expansion.
I'm trying to run a command that takes one location input (intended for a single directory of files), but I need to run it on files in several locations. While I'd normally run it on */*.type, I'm looking for some way to run the command over (*/dirA/*.type AND dirB/*.type).
I basically need all files of *.type within a directory structure, but they're not all at the same directory level (or I'd just do */*/*.type or something to grab them all). Unfortunately they're in a particular layout for a reason, which I can't just reorganize to make this command run.
Is there any bash shortcut/command/whatever-it's-called that I could use to get both sets of files at once?
you can say
dir{A,B}/*.type
For example running this with ls command
root#do:/tmp# ls dir{A,B}/*.type
dirA/test.type dirB/test.type
If the command works when you pass one wildcard in, that means it is expecting a list of file names. In that case you can pass it two wildcards just as easily.
command */dirA/*.type dirb/*.type
In the Maven Windows prerequisites, it states,
You need to unpack the Maven distribution. Don't unpack it in the middle of your source code; pick some location (with no spaces in the path!) and unpack it there.
Why does it matter if there are spaces in the path or not?
The problem is that somewhere in Maven, it is executing a sub process and it is not properly wrapping its file name arguments in double quotes. So a file that is at
"C:\Program Files\Foobar"
will look like 2 files on the command line
"C:\Program"
"Files\Foobar"
and neither of those are correct. This is a holdover from the "old" days when spaces were not allowed in file names (ie 1980s) and spaces separated arguments on the command line. It's a shame that this problem still exists. It's slightly worse on Linux machines, which have been slower to migrate to allowing spaces in file names, so there are more scripts and programs on Linux which fail if you have spaces in the file names.
I have written a batch script that logs into my ftp server, then navigates to a directory. I am having trouble with the mget command, I want it to download every .dat file in the directory, but it simply returns this error:
Cannot access file '/home/minecraft/multicraft/servers/server267/world/players/*.dat':No such file or directory.
200 Type set to: ANSI
Cannot find list of remote files
Here is my script (ran from cmd)
open 66.71.244.202
USER
PASSWORD
cd /world
cd players
mget *.dat
That is by design. The most recent update to the FTP specification (RFC 3659) explicitly forbids it (see section 2.2.2):
For the commands defined in this specification, all pathnames are to be treated literally. That is, for a pathname given as a parameter to a command, the file whose name is identical to the pathname given is implied. No characters from the pathname may be treated as special or "magic", thus no pattern matching (other than for exact equality) between the pathname given and the files present in the NVFS of the server-FTP is permitted.
Clients that desire some form of pattern matching functionality must obtain a listing of the relevant directory, or directories, and implement their own file name selection procedures.
When you execute your script file with ftp, you have to turn off the globbing which will allow the use of wildcards in the script. For example:
ftp -n -i -s:scriptfile.txt
should work but
ftp -n -i -g -s:scriptfile.txt
will not.
I know this is old, but it might help someone. I had the same issue with wildcards on MGET from Windows FTP, but it was not consistent in that it worked talking to some remote systems, but not to all of them.
My script was doing this:
cd /folder/folder
mget ./-400TA/folder/*_XYZ
In the folder structure I have a set of different folders that begin with hyphens, and for whatever reason the script CD's down to just above there, and uses the relative path in the MGET. I had the same issue that some of you reported, that if I connected interactively and typed the commands one by one, it worked. But in batch, it didn't.
I followed the suggestions in this and other posts, but no joy. I don't have access to the remote systems at the moment to look at them to figure out why some worked and some didn't.
However, what I did find was this. Changing my script as follows:
cd /folder/folder/-400TA/folder
mget *_XYZ
did the trick. Simple. There's some strange interaction going on somewhere possibly with folder protections or something, but it just shows that trying out different things may get you there in the end.
I would make sure glob is on, when turned off the file name in the put and get commands is taken literally and wildcards will not be looked at.
More info:
glob:Toggle filename expansion for mdelete, mget and mput. If globbing
is turned off with glob, the file name arguments are taken literally
and not expanded. Globbing for mput is done as in csh. For mdelete and
mget, each remote file name is expanded separately on the remote
machine and the lists are not merged. Expansion of a directory name is
likely to be different from expansion of the name of an ordinary file:
the exact result depends on the foreign operating system and ftp
server, and can be previewed by doing ‘mls remote-files -’ Note: mget
and mput are not meant to transfer entire directory subtrees of files.
That can be done by transferring a tar archive of the subtree (in
binary mode).
Once you are inside your ftp try to check the glob and set it on if it is off. The default behaviour is on, from the command line when connecting to ftp with the option -g you can turn off the file name globbing.
It could very well also be a firewall issue where it is not permitting or forwarding the servers inbound connection. Happened to me.