So, I'm trying to write a line of that will check if there is a directory present, and only try and create a directory if that is false. Found this on Statalist:
local name test_directory
cd C:\
capture confirm file "./`name'/nul" // check if `name' subdir exists
if _rc { // _rc will be >0 if it doesn't exist
!md "`name'"
}
// my do file
save "C:/`name'/current_data.dta" // optionally add -,replace-
Looks pretty solid overall for my application, but I'm struggling with converting it to Mac compatible syntax.
local name test_directory
cd ~/
capture confirm file "./`name'/*"
// check if `name' subdir exists
if _rc {
mkdir "`name'"
}
Any advice on how to do this right?
You can try relying on the return code of the cd command. This is the approach taken by confirmdir (from SSC):
local somedir /home/roberto/Desktop/test
quietly capture cd `"`somedir'"'
if (_rc) display as text "return code `=_rc'; do something, like mkdir"
else display as text "could change dir; the dir exists"
This will signal if
cd was unable to change to the directory you typed because either it
does not exist, it is protected, or it is not a directory
Source: search r(170).
If you plan on issuing several commands after the conditionals, then you need the if {...} else {...} syntax. See help ifcmd.
If you don't want to end up in a different directory, you can save the current one at the beginning
local cwd `"`c(pwd)'"'
and switch back to it when your done:
quietly cd `"`cwd'"'
It should work on both MS Windows and Unix-type OS. (But I can't test on MS Windows.)
I usually use the shell for things like this:
local name test_directory
cd ~
!if test -d `name'; then echo "`name' Already Exists"; else mkdir `name'; fi
I don't really understand why your second code fails.
The problem is the asterisk at the end of the capture statement: if test_directory exists but is empty, nothing will match and _rc will be nonzero. Maybe you meant the asterisk to be a "."?
But the slash before that character is also a problem: if a plain file exists named test_directory, the confirm will fail because "test_directory/." does not exist but mkdir will also fail because of the name conflict.
The following works for me, Stata 13.1 on OS X 10.10, with a little extra output for debugging to confirm what path I've taken.
local name test_directory
cd "~/Research/Stata sandbox"
capture confirm file "./`name'"
// check if `name' subdir exists
if _rc {
mkdir "`name'"
display "`name' created"
}
else {
display "`name' already exists"
}
The following works on all platforms
local dir_to_use "whatever_dir_name"
capture mkdir "`dir_to_use'"
Nothing bad will happen if the directory already exists.
Some may find this simple solution for a do-file handy:
local name test_directory
capture mkdir "C:/`name'/"
save "C:/`name'/current_data.dta"
This will make a folder with the name test_directory if this folder is not already present. The code also runs without error if the folder already existed.
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
How can I check if either or file exists in a If Exist statement?
Such as
If exist "C:/Windows/" OR "C:/Windows2" (
Do something
) else (
Something else
)
How would I do this? I just want either or to exist and to do something.
Simple example 1:
#echo off
if not exist "%SystemRoot%\" if not exist "C:\Windows2" goto MissingFolderFile
echo Found either the directory %SystemRoot% or the file/folder C:\Windows2.
rem Insert here more commands to run on either the folder C:\Windows
rem or the file/folder (=any file system entry) C:\Windows2 existing.
goto EndDemo
:MissingFolderFile
echo There is neither the directory %SystemRoot% nor the file/folder C:\Windows2.
rem Insert here more commands to run on neither folder C:\Windows
rem nor file/folder C:\Windows2 existing.
:EndDemo
pause
The Windows command processor is designed for processing one command line after the other which is the meaning of the word batch. The command GOTO is the preferred command to use in a batch file to continue batch processing not on next command line, but another one depending on an IF condition, i.e. change processing from one stack (other word for batch) of command lines to another group of command lines.
Simple example 2:
#echo off
if exist "%SystemRoot%\" goto FolderExists
if exist "C:\Windows2" goto FS_EntryExists
echo There is neither the directory %SystemRoot%\ nor C:\Windows2.
rem Insert here more commands to run on neither folder C:\Windows
rem nor file/folder/reparse point C:\Windows2 existing.
goto EndDemo
:FS_EntryExists
echo The file system entry (file or folder) C:\Windows2 exists.
rem Insert here more commands to run on C:\Windows2 existing.
goto EndDemo
:FolderExists
echo The folder %SystemRoot% exists.
rem Insert here more commands to run on folder C:\Windows existing.
:EndDemo
pause
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
echo /?
goto /?
if /?
rem /?
NOTE:
The directory separator on Windows is \ and not / as on Linux or Mac. The Windows file management automatically replaces usually all / by \ before passing a file/folder argument string without or with a wildcard pattern to the file system as explained by Microsoft in the documentation about Naming Files, Paths, and Namespaces. But the usage of / instead of \ in file/folder argument strings can result nevertheless in unexpected behavior.
Example for unexpected behavior because of using / on running following command line directly in a command prompt window:
for %I in ("%SystemDrive%/Windows/*.exe") do #if exist "%I" (echo Existing file: "%I") else echo File not found: "%I"
This command line outputs a list of executable file names found by FOR in the Windows directory which do not exist for command IF just because of usage of / resulting in getting assigned to the loop variable the found file names without path. So this command line works only if the current directory on system drive is by chance the Windows directory.
The same command line with usage of \ as directory separator:
for %I in ("%SystemDrive%\Windows\*.exe") do #if exist "%I" (echo Existing file: "%I") else echo File not found: "%I"
This command line outputs each file name of the executables in Windows directory as existing file with full path.
Another example:
There is in root directory of current drive a directory Downloads and the current directory on this drive is Temp, for example D:\Downloads is the wanted current directory and D:\Temp is the current directory.
The used command is:
cd /Downloads
The result is the error message:
The system cannot find the path specified.
The command with correct directory separator usage:
cd \Downloads
This command works on D:\Temp being the current directory and D:\Downloads existing.
CD interprets on incorrect /Downloads the string /D at beginning of the directory path as option /D to change also the drive and searches for that reason for ownloads in current directory instead of Downloads in root directory of current drive. This wrong interpretation by CD is avoided by using the correct directory argument string \Downloads.
SUMMARY: \ is the directory separator and / is for command options.
I am working with a bunch of txt files(thousands) on my project. Each txt file has 'csv' information on it. The problem is that each txt file has a random name and I cannot create a code for loading them in my project due to it. So, I want to rename them in a particular pattern to make easier the loading of the files in my work. I will use C++ for accomplish this task.
I put all the txt files in a folder but I cannot see a way of renaming them using C++. How can I do this? is there a way to do it? Can someone help me?
You can use std::filesystem::directory_iterator and std::filesystem::rename (c++17), as documented here.
Disclaimer
This answer validity is based on a comment where the author precised they were not bound to the C++ language (it may be worth editing the question, the C++ tag, and the OS). This solution may work for UNIX systems supporting bash, that is most Linux distributions and all releases of Apple's macOS prior to macOS Catalina (correct me if I'm wrong).
Bash command line
Using the following bash command should rename all the files in a folder with increasing numbers, that is:
toto.csv -> 1.csv
titi.csv -> 2.csv etc
It assumes the ordering is not important.
a=1; for i in *; do mv -n "$i" "$a.csv" ; let "a +=1"; done
To test it, you can prepare a test folder by opening a terminal and typing:
mkdir test
cd test
touch toto.csv titi.csv tata.csv
ls
Output:
tata.csv titi.csv toto.csv
Then you can run the following command:
a=1; for i in *; do mv -n "$i" "$a.csv" ; let "a +=1"; done
ls
Output:
1.csv 2.csv 3.csv
Explication:
a=1 declare a variable
for i in *; begin to iterate over all files in the folder
do mv will move (rename) a file of the list (that is, the variable $i) to a new name called a.csv
and we increment the counter a, and close the loop.
the option -n will make sure no file gets overwritten by the command mv
I assumed there was no specific criterion to rename the files. If there is a specific structure (pattern) in the renaming, the bash command can probably accommodate it, but the question should then give more details about these requirements :)
I am starting out with F# and trying to get it to work with Sublime Text 3 with a package, https://github.com/fsharp/sublime-fsharp-package. After installing the package using Package Control, I see F# appear as an available language to use in Sublime Text's bottom bar, and syntax highlighting appears to work more or less, from what I can tell, but the build system for F# fails to appear as it should.
So, trying to fix things, I run "build.sh install" and get an error, "Cannot open assembly '.paket/paket.bootstrapper.exe': No such file or directory." I am sort of stuck. Many thanks for any help.
From the comments you've made, you appear to be a little unfamiliar with the Unix underpinnings of OS X. I'll explain those first, then I'll suggest something for you to try that may fix your problem.
Technically, files or directories whose name starts with . are not "reserved for the system" as you put it; they're hidden. Now, it's true that Finder won't allow you to create files or directories whose name starts with ., because Apple didn't want to have to field all the tech-support calls from people who didn't know about the hidden-files feature: "I named my file ... more important stuff for work and now it's gone! Help!!!" But if you're in the Terminal app, then you can easily create files or directories with . as their first letter: mkdir .foo should work. You won't see it when you do ls, but ls -a (a for "all") will show you all files, including hidden files. And you can also do cd .foo and create files inside the hidden .foo directory -- and while the .foo folder won't show up in Finder, it will be perfectly accessible in the Terminal, and to any F# programs you might write.
So when you say that you cloned https://github.com/fsprojects/Paket but it failed to include the .github and .paket directories, I think you just don't know how to see them. You can't see them in the Finder (well, you can if you jump through a couple of hoops but I don't think it's worth the effort), but you can see them with ls -a. Just open your terminal, run cd /Users/Username/Paket, and then run ls -a and I think you'll see that the .paket and .github directories were indeed created by your git clone command.
So what you should probably try is this:
Go to https://github.com/fsprojects/Paket/releases/latest
Download the paket.bootstrapper.exe and paket.exe files. Put them in /Users/Username/Downloads (or wherever the default OS X Downloads directory is if it's different -- just as long as it's somewhere where you can find them easily).
Open the Terminal app.
Go to the directory where you've unpacked the Sublime Text 3 package. I.e., in the Terminal app, run cd /Users/Username/Library/Application\ Support/Sublime\ Text\ 3/Packages/sublime-fsharp-package-master.
Run ls -a and see if there's a .paket directory.
If it does not exist, run mkdir .paket.
Now do cd .paket so you're in the hidden .paket directory under sublime-fsharp-package-master.
Now do ls and see if there's a paket.bootstrapper.exe file.
If it doesn't exist, then copy in the .exe files you downloaded earlier:
cp /Users/Username/Downloads/paket.bootstrapper.exe .
cp /Users/Username/Downloads/paket.exe .
Important: Now do cd .. to go back up to the /Users/Username/Library/Application\ Support/Sublime\ Text\ 3/Packages/sublime-fsharp-package-master/ directory.
Now instead of running /Users/Username/Library/Application\ Support/Sublime\ Text\ 3/Packages/sublime-fsharp-package-master/build.sh install, try running it as ./build.sh install. (And also try ./build.sh Install, since I'm pretty sure the capital I is necessary).
(BTW, If you're not familiar with the syntax that I used in steps 9, 10 and 11, where I used a single . or two dots .. in commands, those are a long-standing Unix idiom: . means "the current directory", and .. means "the parent directory".)
I just looked at the build.sh script that you've been running, and it seems to assume that you've done a cd into the package's base directory (the sublime-fsharp-package-master directory) before running the script. So that could explain why it was failing: you were running it from a different directory, rather than doing a cd first. Hence why I marked step 10 as important: I think that was the root cause of the problem.
I did a ctags -R on my project which is in c++, in the directory /project/ntopng. Now, when I start cscope using cscope -R and search for main.cpp, it opens up. But, when I hit ctrl-] on #include "ntop-includes.h" in main.cpp, the error message is tag not found. The header file is inside a sub-directory in /project/ntopng/include. But, ctags -R is recursive so why is it that I am getting an error? I am using Ubuntu 12.04 with the latest version of ctags and cscope. Thank You.
I have given the below answer for Ubuntu 12.04
1. Open any file with vim
2. type :echo &tags ,It will show what path vim is using for tags file.
If it is not the expected tag file path type:
:set tags=path_to_your_tag_file (ex /project/ntopng/tags)
Remember it is valid for the current session only, Now if permanent changes required there are two options.
For All users (requires root privileges) --
1. cd /etc/vim
2. vim vimrc
3. Go to end and add set tags+=tags;path_to_your_tag_file
For the individual user:
1. cd ~
2. vim .vimrc (This file may not exists in that case newly created)
3. set tags+=tags;path_to_your_tag_file
Let me know if it worked for you.