How to stop recursive symbolic link - symlink

I have a the following folder :
Folder A
Folder B (which is a symbolic link to Folder A)
The issue is that when I access Folder B, I can go infinitely deeper (ie Folder A > Folder B > Folder B > Folder B) because Folder B is inside Folder A.
Is there any way to ignore Folder B after accessing it via Folder A ?
Thank you very much!

The find command detects symbolic link loops and will print a warning message instead of traversing them repeatedly. For example, using the -L option to follow symlinks may print this warning:
$ find -L /some/path
find: File system loop detected; `/some/path/link' is part of the same file system loop as `/some/path'.
From the man page:
The find utility shall detect infinite loops; that is,
entering a previously visited directory that is an ancestor of
the last file encountered. When it detects an infinite loop,
find shall write a diagnostic message to standard error and
shall either recover its position in the hierarchy or
terminate.

To any programmers looking here (cmdline tool questions should instead go to unix.stackexchange.com):
You should know that the Linux/BSD function fts_open() gives you an easy-to-use iterator for traversing all sub directory contents while also detecting such symlink recursions.
Most command line tools use this function to handle this case for them. Those that don't often have trouble with symlink recursions because doing this "by hand" is difficult (any anyone being aware of it should just use the above function instead).

Related

Bash/shell/OS interpretation of . and .. — can I define ...?

How do . and .., as paths (vs. ranges, e.g., {1..10}, which I'm not concerned with), really work? I know what they do, and use them all the time, but don't fully grasp how/where they're interpreted. Does the shell handle them? The interpreting process? The OS?
The reason why I'm asking is that I'd like to be able to use ... to refer to ../.., .... to refer to ../../.., etc. (up to some small finite number; I don't need bash to process an arbitrarily large number of dots). I.e., if my current directory is /tmp/let/me/out, and I call cd ..., my resulting current directory should be /tmp/let. I don't particularly care if ... etc. show up in ls -a output like . and .. do, but I would like to be able to call cat /tmp/let/me/out/..../phew.txt to print the contents of /tmp/phew.txt.
Pointers to relevant documentation appreciated as well as direct answers. This kind of syntax question is very hard to Google.
I'm using bash 4.3.42, by the way, with the autocd and globstar shell options.
. and .. are genuine directory names. They are not "sort-cuts", aliases, or anything fake.
They happen to point to the same inode as the other name you use. A file or directory can have several names pointing to the same inode, these are usually known as hard links, to distinguish them from symbolic (or soft) links.
If you are on Linux or OS X you can use stat to look at most of the inode metadata - it is what ls looks at. You will see there is an inode number. If you stat . and stat current-directory-name you will see that number is the same.
The one thing that is not held in the inode is the filename - that is held in the directory.
So . and .. reside in the directory on the file system, they are not a figment of the shell's imagination. So, for example, I can use . and .. quite happily from C.
I doubt you can change them - personally I have never tried and I never will. You would have to change what these filenames linked to by editing the directory. If you managed it you would probably do irreparable damage to your file system.
I write this to clarify what has already been written before.
In many file systems a DIRECTORY is a file; a special type of file that the file system identifies as being distinctly a directly.
A directory file contains a list of names that map to files on the disk
A file, including a directly does not have an intrinsic name associated with it (not true in all file systems). The name of a file exists only in a directory.
The same file can have an entry in multiple directories (hard link). The same file can then have multiple names and multiple paths.
The file system maintains in every directory entries for "." and ".."
In such file systems there are always directory ENTRIES for the NAMES "." and "..". These entries are maintained by the file system.
The name "." links to its own directory.
The name ".." links to the parent directory EXCEPT for the top level directory where it links to itself (. and .. thus link to the same directory file).
So when you use "." and ".." as in /dir1/dir2/../dir3/./dir4/whatever,
"." and ".." are processed in the exact same way as "dir1" and "dir2".
This translation is done by the file system; not the shell.
cd ...
Does not work because there is no entry for "..." (at least not normally).
You can create a directory called "..." if you want.
You can actually achieve something like this, though this is an ugly hack:
You can run a command before every command entered to bash, and after every command. For that you trap the DEBUG pseudo signal and set a command to PROMPT_COMMAND, respectively.
trap 'ln -s ../.. ... &>/dev/null | true' DEBUG
PROMPT_COMMAND='rm ...'
With this, it seems like there's an additional entry in the current directory:
pwd
# /tmp/crazy-stuff
ls -a
# . .. ... foo
ls -a .../tmp/crazy-stuff
# . .. ... foo
Though this only works in the current directory, because the symbolic links is deleted after each command invokation. Thus ls foo/bar/... won't work this way.
Another ugly hack would be to "override" mkdir such that it populates every new directory with these symbolic links.
See also the comments on the second answer here, particularly Eliah's: https://askubuntu.com/questions/327126/what-is-a-dot-only-named-folder
Much in the same way that when you cd into some directory subdir, you're actually following a pointer that points to that directory, .. is a pointer added by the OS that points to the parent directory, and I'd imagine . works the same way.

vim set tags with absolute path

I work on multiple projects, each ~3-5 million lines of code. I have a single tags file at the root of each project. I also have a tools directory shared between all of them.
disk1
|
+--Proj A
|
+--Proj B
|
+--Shared
disk2
|
+--Proj C
|
+--Proj D
When using tags, I would like Vim to first search the tags file at the root of my project, and then search the tags file for Proj X, and then search the tags file in Shared
I can't get Vim to find the tags file in Shared
in my .vimrc file I have:
set tags=tags;D:/Shared
set tags=tags;,D:/Shared (thanks to romainl for catching a missing comma!)
but Vim only searches the local project tags file, not the shared one.
tags; should start at the CWD and traverse back up the tree until a tags file is found (finds the correct one at the project level).
D:/Shared is an explicit path and should find the tags file in that directory but fails to do so (I've checked, it does in fact exist).
I'm using Exuberand Ctags v5.8
set tags=tags;D:/Shared
means "look upward for a tags file from the current directory until you reach D:/Shared".
If you work in project C on disk 2 (let's call that disk E:), Vim will never visit D:/Shared because of two things:
Upward search is not recursive.
If no tags file is found at the root of the "current directory", Vim tries to find one at the root of its parent and so on until it reaches the topmost parent or the directory you specified after the semicolon. So, supposing you are editing E:\ProjectC\path\to\some\file, you can't expect Vim to find a tags file outside of that path. Vim will search for the following tags files, sequentially and, by the way, never find that hypothetic D:\Shared:
E:\ProjectC\path\to\some\tags <-- KO
E:\ProjectC\path\to\tags <-- KO
E:\ProjectC\path\tags <-- KO
E:\ProjectC\tags <-- OK!
E:\tags <-- KO
It won't find any tags file not listed above.
Windows doesn't have the equivalent of UNIX's "root" directory anyway.
When you don't specify a stop directory, upward search climbs the inverted tree of your filesystem from the current directory (or an arbitrary start directory) to the root of the filesystem.
Supposing you are still editing E:\ProjectC\path\to\some\file, upward search will ultimately look for the stop directory D:\Shared directly under every parent directory in the path to E:\ and will rather obviously never find it.
If you want Vim to find D:\Shared\tags wherever you are, you only need to add it explicitely to the tags option. Not as a stop directory but as a specific location:
set tags=tags;,D:/Shared/tags
Now, it says "look upward for a tags file from the current directory and use D:/Shared/tags".
Hmm… that was a lot of words just to explain the need for a single ,.

cleartool ls: Error: Pathname is not within a VOB: "."

I am trying to use cleartool to browse some CC repositories. I can get a list of VOBs from lsvob but when I pick a VOB entry, cd into it, and try to do ls . to see what's inside, I get the following error message:
cleartool> ls .
cleartool: Error: Pathname is not within a VOB: "."
The following link says I have to be within a view to run ls but how do I know where to go if I can't get a directory listing -- or a view listing to go to.
http://ejostrander.com/cc_errors.html#ERROR19
It seems kind of like you have to already know where you wanna go to and can't get a list of choices.
Question: How do I go past this point?
Thanks
You must be on Unix in order to be able to do a cd /vobs/aVobTag, but that won't give you anything as long as you aren't in a view (or as long as you didn't do a cleartool setview aViewTag, which would allows /vobs/aVobTag do display anything: see "ClearCase setview").
Plus those are for dynamic view consultation, which means you need to mount the Vob first (cleartool mount)
Create a view first, I recommend a dynamic one (easier and quicker to setup: see "How to open a dynamic view in clear case with a given config specs using command prompt?" as an example), and go to:
cleartool mount /vobs/aVobTag
cd /view/yourView/vobs/aVobTag
You will see files there, provided you had checked in files on the /main branch, since the default config spec of a Base ClearCase view is element * /main/LATEST: see "Config spec in Rational ClearCase".

Excluding folders in Winrar

A Day with Winrar
All I wanted to do was exclude folders and their contents using wildcards, and even after reading the docs, it turned into a guessing game...
So my test bed looks like:
C:\!tmp1\f1
C:\!tmp1\f1\f1.txt
C:\!tmp1\f1\a
C:\!tmp1\f1\a\a.txt
C:\!tmp1\f2
C:\!tmp1\f2\f2.txt
C:\!tmp1\f2\a
C:\!tmp1\f2\a\a.txt
And I am executing:
C:\>"c:\program files\winrar\winrar.exe" a -r !tmp1.rar !tmp1
which gives me a rar with !tmp1 as the root (sole top level folder).
The exclude switch is -x<filepathpattern> and may be included multiple times.
So, given that we want to exclude f2, and all its subcontents...
-x*\f2\*
removes the contents, but leaves f2
-xf2
does nothing - includes all
-x\f2
does nothing - includes all
-x*\f2
does nothing - includes all (now I'm mad), so surely it must be..
-x\f2\
nope, does nothing - includes all. So it has GOT to be...
-x*\f2\
hell no, does nothing - includes all. and I already know that
-x*\f2\*
removes the contents, but leaves f2. Onward we go...
-x*f2\
does nothing - includes all. Grrrr. Aha! how about...
-x!tmp1\f2\
nope, does nothing - includes all. WTF. Alright, So it has GOT to be...
-x!tmp1\f2
Holy moly, it worked! Hmmm, then how come....
-x*\f2
does not work? This was the little demon that sent me down this crazed path to begin with and should have worked!
Given all that, do I dare try to go after */a/* directories, removing contents and the dirs?
-x*\a
does not work, of course, does nothing.
-x*\*\a
does not work, of course, does nothing.
-x!tmp1\*\a
nope. But...
-x*\a\*
removes contents of both dirs, but leaves the folders. So, in desperation I can use the -ed switch which will not store empty folders, but this is a broad hack, I want to eliminate the folders specified not all empty folders.
With my animosity growing toward winrar, I am passing the baton of information forward with an eye to that glorious day when we will know how to specifically exclude a folder and its contents using wildcards and not using the -ed switch.
(Quite old question but still may be relevant)
Maybe what you simply needed was this :
-x*\f2 -x*\f2\*
two exclude switches, should remove directory f2 and all its contents.
An even older question by now, but came across this question so I reproduced your folder structure and, at least nowadays (Winrar 5.11, not the latest but quite new), this works:
-x*\f2
So the whole command line is:
"C:\Program Files\WinRAR\Rar.exe" a -m5 -s !tmp1.rar !tmp1 -x*\f2
And this is what is stored in the .rar file:
!tmp1\f1\a\a.txt
!tmp1\f1\f1.txt
!tmp1\f1\a
!tmp1\f1
!tmp1
Similarly, if you use -x*\a, all a folders are excluded, storing this:
!tmp1\f1\f1.txt
!tmp1\f2\f2.txt
!tmp1\f1
!tmp1\f2
!tmp1
Finally, combining both parameters (-x*\f2 -x*\a), you get this:
!tmp1\f1\f1.txt
!tmp1\f1
!tmp1
To manage large list of files to be excluded, you can create text fie and write all excluded files/folders relative to the source folder:
1) create file list.txt, write the name of excluded files/folders
note: * refer to the source, all files/folders are relative to the source folder
*\f2
*\f3
2) Run the command
rar a -r -x#list.txt target.rar source-folder

Make binary believe it is in another directory

On a Linux system I have a binary (bin.exe) which needs to read an input file (input.cfg), where the names of other data files (data.txt) are specified. Usually both binary, input file and data files were in the same directory. Now and for organization reasons I need binary file to be in $SOMEPATH/bin and input and data files in $SOMEPATH/input.
I do not know how to do this. If I try
$SOMEPATH/bin/bin.exe $SOMEPATH/input/input.cfg
I get
error, "data.txt" not found
One solution would be to include absolute of relative path of "data.txt" in input.cfg, but the binary does not accept this.
I thought about somehow fooling the binary so that it thinks it is in $SOMEPATH/input, so that I just do
$SOMEPATH/bin/bin.exe input.cfg
and it works, but I do not know whether this is possible. any hints?
(cd $SOMEPATH/input && $SOMEPATH/bin/bin.exe input.cfg)
This is assuming that the program is relying on the current working directory to find the files. If the program is trying hard to find them in the same location as the executable, by consulting /proc/<pid>/exe for example, then you may be out of luck.

Resources