How to compare two rfs directories with `diff`? - linux

I have two rfs dirctories I would like to compare to each other with diff. Both directories represent a rfs of some other system, and may contain links. If those links are absolute, they will point to something useless.
For example, I have one rfs with the following symlink (inside the rfs):
/usr/test -> /home/test/file1
Now I have this complete rfs inside a directory named /home/user/compare, and the absolute paths of both files mentioned above are
/home/user/compare/usr/test
/home/user/compare/home/test/file1
Clearly, the symlink /home/user/compare/usr/test does not point to the right file. And because of that a comparison with the files in /home/usr/compare with some other rfs directory will fail for those symlinks.
Is it possible to setup diff so it assumes not / as root but /home/user/compare as root (for the comparison), so that the given absolute symlink points to something valid, and diff takes it into account?
Maybe there is a similar Linux command I can use for that?

Related

Bash, normalize case in paths under dir

I have a directory with files and other directories inside. I want to normalize all file paths inside it to lower-case. By this I mean that:
Whenever there are two paths ./A/b/d and /a/b/c under the directory (that I call .). Then A and a should be merged, with the name a. This can occur at any level.
Suppose that there are no file repetitions. That is, if all paths are converted to lowercase, there will be no file conflicts (but many directories will have to be merged).
How can I do this?
In case you are wondering, I am trying to copy a directory from linux to Mac (which is case-insensitive).

Which path can i use inside my program that will fit other computers? (that also have ubuntu)

I made a program in QT c++ that creates some files and i want them to be saved in a specific directory, i created a directory and i moved all the program there so i can use that same directory to save them, but when i write the path to save the files i have to write:
/home/"the name of my computer"/my_program/file.txt
and i want to use this same program in different computers. I also tried just writing:
my_program/file.txt
but it doesn't work.
Your relative path approach was already good, but a relative path is treated as relative to the working directory of the process and that depends on how the program is started.
E.g. if you start it from a shell, then the shell's current working directory will be the program's, if you start it from a launcher menu, it is often the user's home directory, but could be the location of the binary, etc.
So it is better to create a path based on well known base paths. such as the user's home directory, see QDir::home() or the a common location depending on type of data, see QStandardPaths
Did you try home directory path with "~/", many applications save their settings in ~/.applicationName directory

What is double dot(..) and single dot(.) in Linux?

The ls -ai command shows that . and .. have their inodes the same as the current directory and parent directory, respectively.
What exactly are . and ..?
Are they real files or even hard links? But as I have known, it's not allowed to create a hard link to a directory.
. represents the directory you are in and .. represents the parent directory.
From the dot definition:
This is a short string (i.e., sequence of characters) that is added to
the end of the base name (i.e., the main part of the name) of a file
or directory in order to indicate the type of file or directory.
On Unix-like operating systems every directory contains, as a minimum,
an object represented by a single dot and another represented by two
successive dots. The former refers to the directory itself and the
latter refers to its parent directory (i.e., the directory that
contains it). These items are automatically created in every
directory, as can be seen by using the ls command with its -a option
(which instructs it to show all of its contents, including hidden
items).
They are special name-inode maps which do count as hard-links (they do increase the link-count) though they aren't really hard-links, since, as you said, directories can't have hard-links. Read more here: Hard links and Unix file system nodes (inodes)
. represents the current directory that you are using and
.. represents the parent directory.
Example:
Suppose you are in the directory /etc/mysql and you wanted to move to the parent directory, i.e. /etc/. Then use cd..:
/etc/mysql> cd ..
And if you wanted to set the path of one file in the current directory bash file, use . with file name like this: ./filename
They are not hard links. You can more think of it like a shorthand for this directory (.) and parent of this directory (..).
Try to remove or rename . or ... Then you understand why it is not a hard link.

How to convert absolute path to relative in c linux

I would like to know how an absolute path of a symbolic link can be converted to relative based on a given directory (that includes the linked file) in c language on linux (Ubuntu) OS.
I thought searching for the sub-string of the relative path, but what if it already exists higher in the folder's hierarchy?
Here is a more specific description of what I want to do:
Relative path:
folder/folder1/folder2
Absolut path:
/home/giorgos/Desktop/folder/folder1/folder2/a.pdf
changed to
/home/giorgos/Desktop/myfolder/folder1/folder2/a.pdf
Obviously I cant' simply search for and replace "folder/", consider this case:
/home/giorgos/Desktop/folder/folder/folder/folder1/folder2/a.pdf
It can be searched both forwards and backwards and if replaced it still gives a wrong output
Only if I knew the relative path I could search the absolute backwards and replace it, then the output would be correct:
/home/giorgos/Desktop/folder/myfolder/folder/folder1/folder2/a.pdf
Converting a path to relative is a matter of first seeing how many base atoms are shared between the two paths, and then inserting ../ to navigate backwards up the tree before navigating down the correct branch. IE going from: /foo/bar/some/path to /foo/other/path you'll first see that they share /foo, to navigate upwards to that point you need 3 ../, turning the relative path into /foo/../../../other/path . There's a boost::filesystem example for C++ here , save for the C++ & boost::filesystem the same can be done in C.
I'd be seriously tempted to make the decision, if I were writing this tool, that absolute symbolic links should have the same value when moved somewhere else in the filesystem -- the user wanted a very specific file. And, relative symbolic links should have the same value when moved somewhere else in the filesystem -- the user wanted the links to work regardless of where the directory tree was rooted.
But if the two types of links were intermixed, then you'd have some more work to do -- which is where I assume you are now. (Unix programs are often not that forgiving about guessing a user's intent; if you just readlink(2) and symlink(2) exactly what the filesystem says, your program will never be surprising.)
rsync(1) might have some source code you can use -- or at least learn from. The --safe-links command line option causes rsync to ignore absolute symbolic links and relative symbolic links that point outside the trees it was instructed to copy. This isn't canonicalizing paths to relative as you wish but it may provide sufficient code for discovering which links point outside the directory tree in question.
Slightly related; the Linux-specific symlinkat(2) system call may make it easier for you to create your symbolic links. (The family of ...at() system calls are something like providing a process with multiple "current working directories" without forcing you to make all the fchdir(2) calls yourself.)
Well at first I didn't consider the following as important information, but with the help of a function I found out the absolute path to the original and copy directories.
This way I could finally get the original's folder "relative path" (path starting from original folder) change the root node of the dir's tree name to the copied folder's then get the absolute path of the copied folder and append the copied "relative path" and that was it!
realpath(directory,absolutePath);
This is what my code looks like :
readlink(A[i].str, oldLink, NAMESIZE);//A is the struct I keep the paths to directory entries
k=0;
j=strlen(absolutPath);
while(oldLink[j]!='\0')
{
fixLink[k]=oldLink[j];
j++;
k++;
}
strcpy(tmpLink,newAbsolutPath);
strcat(tmpLink,fixLink);
symlink (tmpLink,tmpPath);//tmpPath is the name of the link, tmp link is the absolute path to the actual file
//tmpPath is built almost the same way
So far it runs without any bugs

inotify --fromfile directive

I have a system fedora 15 with xfce window manager.
I installed an inotify util to play with.
I want to control, what happens with my files during my work process.
There is a command which i use today for running inotify
inotifywait --fromfile ~/list.inotify
That command easy read a list of folders and files to read and to ignore.
There is my list (list.inotify)
/home/alex
#/home/alex/Torrnets/
#/home/alex/.pulse-cookie
So it should read my home folder and ignore Torrents folder and .pulse-cookie file.
It ignores Torrents as well. But it won't ignore a .pulse-cookie file.
Any solution for this ? (please don't post a solution to use pattern based ignore, i want to work with a file list with absolute path's)
$man inotify
#<file>
When watching a directory tree recursively, exclude the specified file from being watched. The file must be specified with a relative or absolute path according to whether a relative or absolute path is given for watched directories. If a specific
path is explicitly both included and excluded, it will always be watched.
Note: If you need to watch a directory or file whose name starts with #, give the absolute path.
--fromfile <file>
Read filenames to watch or exclude from a file, one filename per line. If filenames begin with # they are excluded as described above. If <file> is `-', filenames are read from standard input. Use this option if you need to watch too many files to
pass in as command line arguments.
If you don't specify a -e argument, inotifywait will call inotify_add_watch with IN_ALL_EVENTS, which causes events to occur for files inside watched directories - note that inotify(7) says:
When monitoring a directory, the events marked with an asterisk (*) above can occur for files in the directory, in which case
the name field in the returned inotify_event structure identifies the name of the file within the directory.
If you have a look at the inotifywait code in question, you'll see that it only watches (and checks the exclude list against) directories. It would perhaps be a bit more user friendly if you were warned when specifying an exclusion that is not a directory or one that is never used, but that's the way it currently it is.

Resources