I am writing a shell script that takes file paths as input.
For this reason, I need to generate recursive file listings with full paths. For example, the file bar
has the path:
/home/ken/foo/bar
but, as far as I can see, both ls
and find
only give relative path listings:
./foo/bar (from the folder ken)
It seems like an obvious requirement, but I can't see anything in the find
or ls
man pages.
How can I generate a list of files in the shell including their absolute paths?
This question is related to
linux
command-line
absolute-path
ls
find / -print
will do this
Command: ls -1 -d "$PWD/"*
This will give the absolute paths of the file like below.
[root@kubenode1 ssl]# ls -1 -d "$PWD/"*
/etc/kubernetes/folder/file-test-config.txt
/etc/kubernetes/folder/file-test.txt
/etc/kubernetes/folder/file-client.txt
This will give the canonical path (will resolve symlinks): realpath FILENAME
If you want canonical path to the symlink itself, then: realpath -s FILENAME
If you give the find command an absolute path, it will spit the results out with an absolute path. So, from the Ken directory if you were to type:
find /home/ken/foo/ -name bar -print
(instead of the relative path find . -name bar -print
)
You should get:
/home/ken/foo/bar
Therefore, if you want an ls -l
and have it return the absolute path, you can just tell the find command to execute an ls -l
on whatever it finds.
find /home/ken/foo -name bar -exec ls -l {} ;\
NOTE: There is a space between {}
and ;
You'll get something like this:
-rw-r--r-- 1 ken admin 181 Jan 27 15:49 /home/ken/foo/bar
If you aren't sure where the file is, you can always change the search location. As long as the search path starts with "/", you will get an absolute path in return. If you are searching a location (like /) where you are going to get a lot of permission denied errors, then I would recommend redirecting standard error so you can actually see the find results:
find / -name bar -exec ls -l {} ;\ 2> /dev/null
(2>
is the syntax for the Borne and Bash shells, but will not work with the C shell. It may work in other shells too, but I only know for sure that it works in Bourne and Bash).
You can do
ls -1 |xargs realpath
If you need to specify an absolute path or relative path You can do that as well
ls -1 $FILEPATH |xargs realpath
If you don't have symbolic links, you could try
tree -iFL 1 [DIR]
-i
makes tree print filenames in each line, without the tree structure.
-f
makes tree print the full path of each file.
-L 1
avoids tree from recursion.
You can use
find $PWD
in bash
Use this for dirs (the /
after **
is needed in bash to limit it to directories):
ls -d -1 "$PWD/"**/
this for files and directories directly under the current directory, whose names contain a .
:
ls -d -1 "$PWD/"*.*
this for everything:
ls -d -1 "$PWD/"**/*
Taken from here http://www.zsh.org/mla/users/2002/msg00033.html
In bash, **
is recursive if you enable shopt -s globstar
.
You can use
find $PWD
in bash
fd
Using fd
(alternative to find
), use the following syntax:
fd . foo -a
Where .
is the search pattern and foo
is the root directory.
E.g. to list all files in etc
recursively, run: fd . /etc -a
.
-a
,--absolute-path
Show absolute instead of relative paths
stat
Absolute path of a single file:
stat -c %n "$PWD"/foo/bar
readlink -f filename
gives the full absolute path. but if the file is a symlink, u'll get the final resolved name.
Most if not all of the suggested methods result in paths that cannot be used directly in some other terminal command if the path contains spaces. Ideally the results will have slashes prepended. This works for me on macOS:
find / -iname "*SEARCH TERM spaces are okay*" -print 2>&1 | grep -v denied |grep -v permitted |sed -E 's/\ /\\ /g'
If you need list of all files in current as well as sub-directories
find $PWD -type f
If you need list of all files only in current directory
find $PWD -maxdepth 1 -type f
This worked for me. But it didn't list in alphabetical order.
find "$(pwd)" -maxdepth 1
This command lists alphabetically as well as lists hidden files too.
ls -d -1 "$PWD/".*; ls -d -1 "$PWD/"*;
find / -print
will do this
fd
Using fd
(alternative to find
), use the following syntax:
fd . foo -a
Where .
is the search pattern and foo
is the root directory.
E.g. to list all files in etc
recursively, run: fd . /etc -a
.
-a
,--absolute-path
Show absolute instead of relative paths
Most if not all of the suggested methods result in paths that cannot be used directly in some other terminal command if the path contains spaces. Ideally the results will have slashes prepended. This works for me on macOS:
find / -iname "*SEARCH TERM spaces are okay*" -print 2>&1 | grep -v denied |grep -v permitted |sed -E 's/\ /\\ /g'
ls -d "$PWD/"*
This looks only in the current directory. It quotes "$PWD" in case it contains spaces.
Command: ls -1 -d "$PWD/"*
This will give the absolute paths of the file like below.
[root@kubenode1 ssl]# ls -1 -d "$PWD/"*
/etc/kubernetes/folder/file-test-config.txt
/etc/kubernetes/folder/file-test.txt
/etc/kubernetes/folder/file-client.txt
Recursive files can be listed by many ways in Linux. Here I am sharing one liner script to clear all logs of files(only files) from /var/log/
directory and second check recently which logs file has made an entry.
First:
find /var/log/ -type f #listing file recursively
Second:
for i in $(find $PWD -type f) ; do cat /dev/null > "$i" ; done #empty files recursively
Third use:
ls -ltr $(find /var/log/ -type f ) # listing file used in recent
Note: for directory location you can also pass $PWD
instead of /var/log
.
find / -print
will do this
Just an alternative to
ls -d "$PWD/"*
to pinpoint that *
is shell expansion, so
echo "$PWD/"*
would do the same (the drawback you cannot use -1
to separate by new lines, not spaces).
ls -1 | awk -vpath=$PWD/ '{print path$1}'
Here's an example that prints out a list without an extra period and that also demonstrates how to search for a file match. Hope this helps:
find . -type f -name "extr*" -exec echo `pwd`/{} \; | sed "s|\./||"
You might want to try this.
for name in /home/ken/foo/bar/*
do
echo $name
done
You can get abs path using for
loop and echo
simply without find
.
This worked for me. But it didn't list in alphabetical order.
find "$(pwd)" -maxdepth 1
This command lists alphabetically as well as lists hidden files too.
ls -d -1 "$PWD/".*; ls -d -1 "$PWD/"*;
You might want to try this.
for name in /home/ken/foo/bar/*
do
echo $name
done
You can get abs path using for
loop and echo
simply without find
.
Recursive files can be listed by many ways in Linux. Here I am sharing one liner script to clear all logs of files(only files) from /var/log/
directory and second check recently which logs file has made an entry.
First:
find /var/log/ -type f #listing file recursively
Second:
for i in $(find $PWD -type f) ; do cat /dev/null > "$i" ; done #empty files recursively
Third use:
ls -ltr $(find /var/log/ -type f ) # listing file used in recent
Note: for directory location you can also pass $PWD
instead of /var/log
.
You can use
find $PWD
in bash
Just an alternative to
ls -d "$PWD/"*
to pinpoint that *
is shell expansion, so
echo "$PWD/"*
would do the same (the drawback you cannot use -1
to separate by new lines, not spaces).
lspwd() { for i in $@; do ls -d -1 $PWD/$i; done }
Use this for dirs (the /
after **
is needed in bash to limit it to directories):
ls -d -1 "$PWD/"**/
this for files and directories directly under the current directory, whose names contain a .
:
ls -d -1 "$PWD/"*.*
this for everything:
ls -d -1 "$PWD/"**/*
Taken from here http://www.zsh.org/mla/users/2002/msg00033.html
In bash, **
is recursive if you enable shopt -s globstar
.
This will give the canonical path (will resolve symlinks): realpath FILENAME
If you want canonical path to the symlink itself, then: realpath -s FILENAME
find / -print
will do this
Here's an example that prints out a list without an extra period and that also demonstrates how to search for a file match. Hope this helps:
find . -type f -name "extr*" -exec echo `pwd`/{} \; | sed "s|\./||"
readlink -f filename
gives the full absolute path. but if the file is a symlink, u'll get the final resolved name.
The $PWD
is a good option by Matthew above. If you want find to only print files then you can also add the -type f option to search only normal files. Other options are "d" for directories only etc. So in your case it would be (if i want to search only for files with .c ext):
find $PWD -type f -name "*.c"
or if you want all files:
find $PWD -type f
Note: You can't make an alias for the above command, because $PWD gets auto-completed to your home directory when the alias is being set by bash.
You can use
find $PWD
in bash
If you give the find command an absolute path, it will spit the results out with an absolute path. So, from the Ken directory if you were to type:
find /home/ken/foo/ -name bar -print
(instead of the relative path find . -name bar -print
)
You should get:
/home/ken/foo/bar
Therefore, if you want an ls -l
and have it return the absolute path, you can just tell the find command to execute an ls -l
on whatever it finds.
find /home/ken/foo -name bar -exec ls -l {} ;\
NOTE: There is a space between {}
and ;
You'll get something like this:
-rw-r--r-- 1 ken admin 181 Jan 27 15:49 /home/ken/foo/bar
If you aren't sure where the file is, you can always change the search location. As long as the search path starts with "/", you will get an absolute path in return. If you are searching a location (like /) where you are going to get a lot of permission denied errors, then I would recommend redirecting standard error so you can actually see the find results:
find / -name bar -exec ls -l {} ;\ 2> /dev/null
(2>
is the syntax for the Borne and Bash shells, but will not work with the C shell. It may work in other shells too, but I only know for sure that it works in Bourne and Bash).
If you don't have symbolic links, you could try
tree -iFL 1 [DIR]
-i
makes tree print filenames in each line, without the tree structure.
-f
makes tree print the full path of each file.
-L 1
avoids tree from recursion.
stat
Absolute path of a single file:
stat -c %n "$PWD"/foo/bar
ls -1 | awk -vpath=$PWD/ '{print path$1}'
You can do
ls -1 |xargs realpath
If you need to specify an absolute path or relative path You can do that as well
ls -1 $FILEPATH |xargs realpath
The $PWD
is a good option by Matthew above. If you want find to only print files then you can also add the -type f option to search only normal files. Other options are "d" for directories only etc. So in your case it would be (if i want to search only for files with .c ext):
find $PWD -type f -name "*.c"
or if you want all files:
find $PWD -type f
Note: You can't make an alias for the above command, because $PWD gets auto-completed to your home directory when the alias is being set by bash.
If you need list of all files in current as well as sub-directories
find $PWD -type f
If you need list of all files only in current directory
find $PWD -maxdepth 1 -type f
ls -d "$PWD/"*
This looks only in the current directory. It quotes "$PWD" in case it contains spaces.
lspwd() { for i in $@; do ls -d -1 $PWD/$i; done }
Source: Stackoverflow.com