If I have a directory tree that looks like this:
parent/
child/
many files
What command/commands should I use to quickly make it like this:
parent/
many files
Effectively, I just want to remove one level of folder nesting. I don't care about any other files currently in parent.
This is what you do:
cd parent
mv child/* .
rmdir child
If you have files beginning with . (dot) in the child/ directory, you have to do
shopt -s dotglob
in order for the * to match them (there are other ways to force this, but setting dotglob is the easiest).
If child/ contains a file or directory named child, then you have to either rename that or the directory parent/child before the mv operation.
What about this?
mkdir new
find parent -type f -exec mv {} new/. \;
That would work for any depth of directory.
Related
I have a directory named lists, and have several subdirectories in this named as lists-01, lists-02 and so on.
In every subdirectory, I have a sript called checklist.
I want to use grep command to search for "margin" in each script "checklist", and want to know the particular checklist scripts which contain the word "margin".
I tried using
grep "margin" list*/checklist
but, this is not giving any result.
You can make use of --include to select just the files you want:
grep -Rl --include='*checklist' "margin" .
I am trying to figure out how to include list-0*/ directories, still couldn't find a way.
Note also that your attempt was quite accurate. You only need to add -R for recursive:
grep -R "margin" list-[0-9]*/checklist
How about:
find lists -name checklist -type f -exec grep -H margin {} \;
That says... find, starting in the directory called lists, and all directories below, all files called checklist and look in them for the word margin printing the filename if it is in there.
If you have a modern find, you can replace the \; with + to allow each find to search more than one file and make your query more efficient.
It will search all the files named checklist recursively and then run grep command on those files to find word "margin". -l option will give you only file name and option -w is used for exact match.
find ~/list -type f -name checklist -exec grep -lw "margin" {} +
I was reading a book on UNIX when I came across this question.
You have a directory structure
$HOME/a/a/b/c
where the first a is empty.
How do you remove it and move the lower directories up?
I have looked on the man pages of the commands rmdir and rm but could find nothing.
Please help me.
You should move subdirectory before remove parent directory. So..
mv $HOME/a/a $HOME
rmdir $HOME/a
But, this does not work because name a collide.
Rename the parent directory to avoid name collision.
mv $HOME/a $HOME/temp_a
mv $HOME/temp_a/a $HOME
rmdir $HOME/temp_a
Since you cannot move a/a into a, you could instead rename a.
mv a a_
mv a_/a .
rmdir a_
Hi this is a simple question but the solution eludes me at the moment..
I can find out the folder name that I want to change the name of, and I know the command to change the name of a folder is mv
so from the current directory if i go
ls ~/relevant.directory.containing.directory.name.i.want.to.change
to which i get the name of the directory is called say lorem-ipsum-v1-3
but the directory name may change in the future but it is the only directory in the directory:
~/relevant.directory.containing.directory.name.i.want.to.change
how to i programmatically change it to a specific name like correct-files
i can do it normally by just doing something like
mv lorem-ipsum-v1-3 correct-files
but I want to start automating this so that I don't need to keep copying and pasting the directory name....
any help would be appreciated...
Something like:
find . -depth -maxdepth 1 -type d | head -n 1 | xargs -I '{}' mv '{}' correct-files
should work fine as long as only one directory should be moved.
If you are absolutely certain that relevant.directory.containing.directory.name.i.want.to.change only contains the directory you want to rename, then you can simply use a wildcard:
mv ~/relevant.directory.containing.directory.name.i.want.to.change/*/ ~/relevant.directory.containing.directory.name.i.want.to.change/correct-files
This can can also be simplified further, using bash brace expansion, to:
mv ~/relevant.directory.containing.directory.name.i.want.to.change/{*/,correct-files}
cd ~/relevant.directory.containing.directory.name.i.want.to.change
find . -type d -print | while read a ;
do
mv $a correct-files ;
done
Caveats:
No error handling
There may be a way of reversing the parameters to mv so you can use xargs instead of a while loop, but that's not standard (as far as I'm aware)
Not parameterised
If there any any subdirectories it won't work. The depth parameters on the find command are (again, AFAIK) not standard. They do exist on GNU versions but seem to be missing on Solaris
Probably others...
What does . (dot) mean as the destination of the cp command?
For example:
cp ~dir1/dir2/dir3/executableFile.x .
When this executes it copies the file successfully with the correct file name, but I'm wondering is this what a destination of '.' will always do or is there another purpose?
Within the reference material I've seen, dots are used in front of files to indicate 'hidden', but in that has no relation to the command above.
dot represents the current directory
while dotdot is the parent directory.
As EvilTeach's answer says, . is the current directory, and .. is the parent directory.
There are basically two ways to use the cp command:
cp file1 file2
will copy file1 to file2, creating file2 if it doesn't exist or (depending on permissions) possibly clobbering it if it does.
The other way is:
cp file1 file2 ... dir
where dir is an existing directory. With this form, you can specify one or more files, and they'll all be copied into the specified directory dir with their existing names.
(This can be a pitfall sometimes; cp foo bar behaves very differently depending on whether there's an existing directory named bar.)
As you mention, files (including directories) whose names start with . are hidden. What this means is that (a) the ls command won't list them (unless you use the -a or -A option), and (b) a shell wildcard such as * or *.txt will omit them. (GUI directory managers such as Nautilus may also omit them, depending on your settings.)
This applies to the current directory . and the parent directory ... ls won't include the . and .. entries in its output; ls -a will.
I want to delete all files in a directory with a given name, except for one with a given extension. I.e. we have a directory with:
foo.txt foo.exe foo.jpg foo.png foo.something foo.somethingelse bar.jpg bar.exe
I want to get rid of foo.txt foo.jpg foo.png foo.something foo.somethingelse
BUT crucially I don't want to get rid of foo.exe
Is there an easy one liner to do this?
Thank you
You can use ! inside a find command to exclude things, so something like:
find . -maxdepth 1 -type f -name "foo.*" ! -name foo.exe -exec rm '{}' \;
----------- ------- ------------- --------------- ----------------
in this dir files named foo.* but not foo.exe ...destroy them.
That should delete files matching foo.* in the current directory but leave foo.exe alone.