create a new directory under all directories using single command : Linux - linux

Suppse if I have directories
dir_1/ dir_2/ dir_3/
How can I create a directory of same name under all these directories using a single command?

Here is one command for you:
If your want the sub dir have the same name as the parent dir:
for i in ./dir_*; do mkdir -p "${i}/${i}"; done
If you want the sub dir share the same new name.
for i in ./dir_*; do mkdir -p "${i}/new_dir_name"; done

You should use Brace Expansion
mkdir dir_{1..3}/newDir
Only work if you know the names of the dirs in advance, of course.
Doesn’t work with ’sh’ though.

You can use this find:
find . -maxdepth 1 -type d -name 'dir_*' -exec mkdir {}/{} \;
Test:
$ ls
dir_1 dir_2 dir_3 file1 file2 file3
$ find . -maxdepth 1 -type d -name 'dir_*' -exec mkdir {}/{} \;
$ ls dir_1/
dir_1

Using find you could do:
find . -type d -maxdepth 1 -execdir mkdir -p "{}/{}" \;
This will create directory/directory if it doesn't already exist.

Related

How to copy files along with a part of folder structure in unix?

I want to copy all the files from a folder which is more than x days old to a new path.
Source folder structure:
/opt/install/sw1/team/p2.csv
/opt/install/sw2/team/p2.csv
Destination should be:
/work/backup/sw1/team/p2.csv
/work/backup/sw2/team/p2.csv
Will this do:
mkdir /work/backup/sw1/team
find /opt/install/sw1/team -maxdepth 0 -mtime +5 -exec cp '{}' /work/backup/sw1/team \;
mkdir /work/backup/sw2/team
find /opt/install/sw2/team -maxdepth 0 -mtime +5 -exec cp '{}' /work/backup/sw2/team \;
If I understand correctly:
cp -a /opt/install/sw1 /opt/install/sw2
Or for verbose:
cp -av /opt/install/sw1 /opt/install/sw2
-a says to copy everything and preserve permissions. If this is not what you want, then -r might be more appropriate.

Copy all directories except one

I'm copying all subdirectories with its contents to my current directory as follows:
cp -r dirToCopy/* .
But in the folder dirToCopy, there is one subfolder called dirNotToCopy which should not be copied.
How can I filter that particular folder out of my expression?
Use extended globbing:
shopt -s extglob
cp -r dirToCopy/!(dirNotToCopy) .
Well if you want to do it in single line:
find /path_to/dirToCopy -mindepth 1 -type d ! -name dirNotToCopy -exec cp -r {} . \;
One more way of doing the same.
find /path_to/dirToCopy -maxdepth 1 -type d ! -name dirNotToCopy -exec cp -r {} . \;
Instead of using mindepth suggested in the other answer, we should use maxdepth.
(I can't comment or edit another answer since I do not have enough reputation yet)
Also note that this command only copies the subdirectories, not the files in the directory.

Linux find folder and rename

I want to rename all .hg_gg folders in /var/www to .hg. How can I do it?
I know how to rename .hg to .hg_gg.
find /var/www -name ".hg" -exec bash -c 'mv $0 $0_gg' {} \;
but don't know how to make reverse change.
Try this:
find /var/www -name ".hg_gg" -execdir bash -c 'mv {} .hg' \;
You need to use a special syntax defined by find: {} is the placeholder for the current file name. Check the man page for that. Also it is important to use -execdir instead of -exec. execdir changes the current working directory to the folder where the found directory is located. Otherwise it would do something like this mv /var/www/.hg_gg ./.hg
You can speed up things a bit when restricting find to find folders only using -type d:
find /var/www -type d -name ".hg_gg" -execdir bash -c 'mv {} .hg' \;
Consider this find command with -execdir and -prune options:
find /var/www/ -type d -name ".hg_gg" -execdir mv '{}' '.gg' \; -prune
-execdir will execute the command in each subdirectory
-prune causes find to not descend into the current file
Not a one liner, but you could do this:
for file in `find /var/www -name ".hg_gg"`; do
mv $file `echo $file | sed 's/hg_gg$/hg/'`
done

Find and rename a directory

I am trying to find and rename a directory on a linux system.
the folder name is something like : thefoldername-23423-431321
thefoldername is consistent but the numbers change every time.
I tried this:
find . -type d -name 'thefoldername*' -exec mv {} newfoldername \;
The command actually works and rename that directory. But I got an error on terminal saying that there is no such file or directory.
How can I fix it?
It's a harmless error which you can get rid of with the -depth option.
find . -depth -type d -name 'thefoldername*' -exec mv {} newfoldername \;
Find's normal behavior is to process directories and then recurse into them. Since you've renamed it find complains when it tries to recurse. The -depth option tells find to recurse first, then process the directory after.
It's missing the -execdir option! As stated in man pages of find:
-execdir command {};
Like -exec, but the specified command is run from the subdirectory containing the matched file, which is not normally the directory in which you started find.
find . -depth -type d -name 'thefoldername*' -execdir mv {} newfoldername \;
With the previous answer my folders contents are disappeared.
This is my solution. It works well:
for i in find -type d -name 'oldFolderName';
do
dirname=$(dirname "$i")
mv $dirname/oldFolderName $dirname/newFolderName
done
.../ABC -> .../BCD
find . -depth -type d -name 'ABC' -execdir mv {} $(dirname $i)/BCD \;
Replace 1100 with old_value and 2200 with new_value that you want to replace.
example
for i in $(find . -type d -iname '1100');do echo "mv "$i" "$i"__" >> test.txt; sed 's/1100__/2200/g' test.txt > test_1.txt; bash test_1.txt ; rm test*.txt ; done
Proof
[user#server test]$ ls -la check/
drwxr-xr-x. 1 user user 0 Jun 7 12:16 1100
[user#server test]$ for i in $(find . -type d -iname '1100');do echo "mv "$i" "$i"__" >> test.txt; sed 's/1100__/2200/g' test.txt > test_1.txt; bash test_1.txt ; rm test*.txt ; done
[user#server test]$ ls -la check/
drwxr-xr-x. 1 user user 0 Jun 7 12:16 2200
here __ in sed is used only to change the name it have no other significance

Create file in Linux and replace content

I have a project in Linux. I want to create a file named index.html in all folders.
So I have used the following command:
find . -type d -exec touch {}/index.html \;
It's working! Now I'm trying to copy the existing file from a given location and it to be automatically replaced into all the folders of my project.
This should actually work exactly in the same way:
find . -type d -exec cp $sourcedir/index.html {}/index.html \;
If I understand your question correctly, what you want is to copy a given file in all the directories.
You can use a similar find command :
find . -type d -exec cp -f /tmp/index.html {} \;
where /tmp/index.html is path to the original file (replace it with your own path).
Also, you don't need to create the files if your final objective is to replace them with the original file.
tar -cvzf index.tar.gz `find . -type f -iname 'index.html'` && scp index.tar.gz USER#SERVER:/your/projec/root/on/SERVER && ssh USER#SERVER "tar -xvzf index.tar.gz"
Or if you're in the proper directory localhost, and rsync is available:
rsync -r --exclude='**' --include='**/index.html' . USER#SERVER:/your/projec/root/on/SERVER
HTH

Resources