parsing ls -R output into a variable in Unix - linux

I am executing a ls-R /files/
I got the following output
./: nvision
./nvision: layout
./nvision/layout: abcd.txt
I am looking to get path in the listing like
/nvision
/nvision/layout/
/nvision/layout/abcd.txt
and I should be able to copy the required path to a variable
ps: I am not searching for nvision
I am trying to get the list of folders and files under files folder
can any one help me with that

Have you tried using find (see reference)
It would be as easy as find . to get the list of files and folders inside the current directory. Change the . to any path to obtain the list of files and directories inside that path:
nvision
nvision/abcd.txt
nvision/layout
To save it to a variable
var=`find .`
And to add the initial slash to every line (if required)
var=`find . -exec echo /{} \;`
Here var has no special meaning, it's just the variable name.
To later use the variable you can use $var or ${var}. For example, to print it or save it to file:
# Print the variable content
echo $var
# Save the content of var to a file
echo $var > /tmp/file.txt

You should really use find for these kind of things. Simply use find directory. If you require more specific output formatting you can make use of find's -printf option. Find is a really powerful tool that also allows all kinds of filtering. Make sure you check the documentation for more information: GNU FindUtils.
To store the results in a variable use one of the following statements:
result=`find ...`
or
result=$(find ...)
You can also use find to directly execute a command for each match using find's -exec option. Again, make sure to check out the documentation. It's really comprehensive.
Update (Mac / UNIX users – Linux users are not affected)
BSD find requires a path. Use
find .
instead of just
find
if you require a listing of all files in your working directory.

well the answer is all over this page you should be using find which lists all files found yo can define
where . is current folder otherwise replace . with path you are wishing to search
find .-type d -print
which lists directories only or find
or
find . -type f -print
which will list all files only
if you are looking for both then
find . -print
and if you only wish to define recursive level try
find . -maxdepth 1 -print
and here is a script
#!/bin/bash
for names in $(find . -type f -print); do
echo $names
done

Related

Find all files with specific name and move it two levels up from its location

I want to find all files with specific name "stdout.1.0", move it two/three levels up from its location. While moving it two/three levels up, I also want to rename it to "testjob.out".
All "stdout.1.0" files are located six levels down from parent directory.
./dirXXXXXX/dirXXXXXX/dirXXXXXX/dirXXXXXX/dirXXXXXX/dirXXXXXX/stdout.1.0
I used:
find . -type f -name stdout.1.0
and it outputs:
./dir100000/dir110000/dir111000/dir111100/dir111110/dir111111/stdout.1.0
./dir100000/dir110000/dir112000/dir111100/dir111110/dir111111/stdout.1.0
./dir100000/dir110000/dir113000/dir111100/dir111110/dir111111/stdout.1.0
./dir200000/dir210000/dir211000/dir211100/dir211110/dir211111/stdout.1.0
./dir200000/dir210000/dir212000/dir211100/dir211110/dir211111/stdout.1.0
./dir200000/dir210000/dir213000/dir211100/dir211110/dir211111/stdout.1.0
./dir300000/dir310000/dir311000/dir311100/dir311110/dir311111/stdout.1.0
./dir300000/dir310000/dir312000/dir311100/dir311110/dir311111/stdout.1.0
./dir300000/dir310000/dir313000/dir311100/dir311110/dir311111/stdout.1.0
.
.
./dirXXX000/dirXXX000/dirXXX000/dirXXX100/dirXXX110/dirXXX111/stdout.1.0
The directories above is just representative of where the file is, but there are multiple "stdout.1.0" files starting three levels down from parent directory.
Here is a method in plain bash using globstar shell option , without using the find:
#!/bin/bash
shopt -s globstar
for file in **/stdout.1.0; do
echo mv "$file" "${file%/*/*/*}/testjob.out"
done
Drop the echo if output looks fine.
You already know how to find them:
find . -type f -name stdout.1.0
Now, you need to move them to a higher directory (..) and rename them:
find . -type f -name stdout.1.0 -execdir mv {} ../../testjob.out \;
I would advise you to copy them first and remove later (use cp instead of mv): if anything goes wrong, you can get back easily to the current situation.

How can i count the number of files with a specific octal code without them showing in shell

I tried using tree command but I didn't know how .(I wanted to use tree because I don't want the files to show up , just the number)
Let's say c is the code for permission
For example I want to know how many files are there with the permission 751
Use find with the -perm flag, which only matches files with the specified permission bits.
For example, if you have the octal in $c, then run
find . -perm $c
The usual find options apply—if you only want to find files at the current level without recursing into directories, run
find . -maxdepth 1 -perm $c
To find the number of matching files, make find print a dot for every file and use wc to count the number of dots. (wc -l will not work with more exotic filenames with newlines as #BenjaminW. has pointed out in the comments. Source of idea of using wc -c is this answer.)
find . -maxdepth 1 -perm $c -printf '.' | wc -c
This will show the number of files without showing the files themselves.
If you're using zsh as your shell, you can do it natively without any external programs:
setopt EXTENDED_GLOB # Just in case it's not already set
c=0751
files=( **/*(#qf$c) )
echo "${#files[#]} files found"
will count all files in the current working directory and subdirectories with those permissions (And gives you all the names in an array in case you want to do something with them later). Read more about zsh glob qualifiers in the documentation.

Is there any way in which i can goto a directory found out using "find" command?

I would like to use a command that change the current working directory to the one i find out using the "find" command.Is there any way that I can do that on a single line in bash?
I would like to use a command that change the current working directory to the one i find out using the find command.Is there any way that I can do that on a single line in bash?
I want to go to a directory called "mydir".I only know that it is somewhere in "documents". I want to change my current working directory to "mydir".
I know that I can know the path using find -name mydir.
this should do..
$ cd "$(find . -type d -name myDir -print -quit)"
-quit to ensure at most one value is returned (and finish looking after first match), may not be supported in all finds. Otherwise you need to filter the result but will take longer.

Shell Script to finding files in specific folder and based on "age" of files

hello i got homework to make a shell script in linux to find a file in specific folder based on the "age" of those files. and after that i want to move that file to other specific folder.
thank you before
One way is to use the find command, and specify the "age" with -mtime (or -newer if age relative to other files). See man find for more details.
To move the files you can use mv (again, see man mv).
Directories can be passed as arguments or stored in variables and then used
as variables in the commands.
Without knowing anything else about your assignment I'd say use something like this:
find <directory> -mtime <n> | xargs mv -t <destination>
where xargs is used to pass the results from find to the mv command.

Using Perl how can I clean up left over directories with no files?

There is a specific directory which is used as a temp/scratch directory by some program.
E.g. /a/b/c/work
Under work multiple hierarchical directories may exist e.g.
/a/b/c/work/
\d1/
\d1.1
\d2
\d2.2
What I want is to clean up this work directory as there are left over files that take space.
Essentially I need to delete all subdirectories under work that the leaf directory is empty.
So if d1.1 is empty but d2.2 has files then delete everything under d1 (including d1) but not d2.
What is the cleanest/standard way to do this in perl?
I thought to use a solution with backticks e.g. rm -rf etc but I thought there could be some better way than coding sequences of ls folowed by rm
Note: Just to be clear. I want a solution in Perl as this is not a one time thing and I dont want to do this manually each time
If you use find command this way you can achieve it.
find /path/to/dir -empty -type d -delete
Where,
-empty Only find empty files and make sure it is a regular file or a directory.
-type d Only match directories.
-delete Delete files.
Always put -delete option at the end of find command as find command line is evaluated as an expression, so putting -delete first will make find try to delete everything below the starting points you specified.
To automate this in shell script follow below code:
path=`pwd`
find $path -empty -type d -delete
or you can give certain input as arguments of shell script like myShell.sh /path/to/mydir in that case the following code will be do the work,
$path=$1
find $path -empty -type d -delete
As for if you really want to go for perl you can find your answer as follows
use strict;
use warnings;
use File::Util;
my $path = '...';
my $fu = File::Util->new();
my #all_dirs = $fu->list_dir($path, '--recurse', '--dirs-only');
my #empty_dirs = grep { not $fu->list_dir($_) } #all_dirs;
also a short method
perl -MFile::Find -e"finddepth(sub{rmdir},'.')"
which is explained very good here.

Resources