[SOLVED] sed for relative path to a literal path starting at the top of the directory structure in a text file
Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
sed for relative path to a literal path starting at the top of the directory structure in a text file
hi guys,
i have a text file that contains several lines of paths to several files located on my system, with each path on a newline. the paths are relative to my current directory, and i need to make them literal so each of the paths begin at the top level in the directory structure, like this:
Code:
./ABC/more_text.txt
and i want to come out as:
Code:
/topdir/some_text/ABC/more_text.txt
i've been trying to do this with sed commands, and have had some success with the string replacement if the string of the paths do not contain a ./ like this
Code:
ABC/more_text.txt
and it comes out like this
Code:
topdir/some_text/ABC/more_text.txt
but again the relative strings of paths on each new line really look like this:
Code:
./ABC/more_text.txt
and i want to come out as:
Code:
/topdir/some_text/ABC/more_text.txt
so i've been trying without success:
Code:
sed -i 's/\.\/ABC/\/topdir\/some_text/g' file.txt
and i get from standard i/o
Code:
unknown option to 's
what am i missing?
i've also tried this with awk using the sub command without success.
surely this is a relatively common occurance with file string manipulation
(unfortunately, the file is on a different machine and i'm not able to transfer it to this machijne, but i think i've copied over the exact text)
Try using a different separator character - it may be more obvious what you have omitted.
As for the broader question, I prefer a KISS approach - have separate stanzas (-e or separate sed commands) for each element of the problem. Makes it easier to nut out, and usually easier to spot what is happening.
What happens if a name such as "../../some/file" appears in the list ?.
Also, there is an existing utility, realpath, which can resolve the absolute file name when given a relative name. It takes several options so as to make different priorities when working out the absolute path.
See also the utilities basename and dirname, if you need to strip off either just the path or just the filename.
however the file has several hundred lines of paths and it turns out that some of the paths have a whitespace in the path (no doubt caused by a dirty rotten PC user), which i didn't find out until attempting to use a paths half way down the output file, and of course things went sideways, so some of the paths will look more like:
Code:
./ABC/more_text (more_texts)-even_more_text.txt
and using your sed command i do get
Code:
/topdir/some_text/ABC/more_text.txt
knowing to get a linux box to read a path with a white space i need to precede the whitespace with a \ so linux ignores the white space, and so i wrote a "tag on" command using a pipe to your command, namely:
Code:
sed '/^[^\/]/s/^\(\.\/\)\?/\/topdir\/some_text\//' pathfile.txt | sed 's/ /\\ /g' > new_pathfile.txt
but the new_pathfile did not contain a \whitespace as part of the result, the results were the same as had i just run your command, namely my output was:
I think that the suggestions made by Turbocapitalist are likely to help you in the long run.
In the scripts that I've written, I break down various sections of a pathname and when I do so, I'm able to make effective use of the basename and dirname utilities, though I don't recall taking advantage of the realpath - that would also be a useful tool to utilize. The suggestions from syg00 are also good - keeping variables and code paths simple and easy to debug makes the code easier to maintain years down the road, whether it's your change or someone who maintains or copies your work.
When I use one of my old scripts or grab some public code, when simple methods are used, it is so much easier to integrate the work of others into what I'm doing, so keeping your code simple and well documented benefits both you and others.
So some easy things to get your file and path parsing algorithms rock solid:
1. Use common utilities - basename, dirname, realpath to extract specific file elements
2. Use variables to store subsets of the full path
3. Keep the overall code simple and well-documented. If it's understandable, documenting it is easier, so that's yet another benefit of simplicity.
thanks masinick, but i'm not at all that good of a coder/script writer.
i do agree with you on making it well documented and keeping code public so that others can make use if it and as a backup copy for yourself, and i do reuse my previous codes, embed or hack on them as necessary.
Distribution: LFS 9.0 Custom, Merged Usr, Linux 4.19.x
Posts: 616
Rep:
You could go for getting the real path based on the relative path you're already generating. Assuming you have an array of relative paths, including the file name, you can regenerate the text file for each target in whole. With $files as your array...
Code:
for file in $files
do
targetpath=$( realpath $( dirname $file ) )
<call function to write out to files, or save to an array until all are ready>
done
dirname gets the path off the file, realpath gets it's absolute position in the filesystem. Note that if you're using links you should read the man pages for those, I've not had them follow links before.
If you're willing to put something unique in the file names, you can use find. Let's say all of these files will have "-MARKER-" in the name. You could use find to generate an array.
Code:
for file in $( find -name *-MARKER-* )
do
call_update_function($file)
done
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.