I have two directories. dir1 and dir2.
In dir1 files are: abc.txt, abd.txt, abe.txt, abf.txt
In dir2 files are: abi.txt, abd.txt, abe.txt, abg.txt, abh.txt
abd.txt and abe.txt are present in both directories and are having different contents. How to write a script which will return only these two file name?
I dont want files which are missing in dir1 or dir2. I only need file names which has same names and are having different contents.
Thank you in advance.
One indirect way to do so is use diff command
diff -r dir1 dir2 | grep "diff -r"
diff -r dir1 dir2 will show differences of files with same name with filenames as diff -r dir1/file dir2/file. Rest of the files will be listed with prefix Only.
Hope someone suggests a simpler solution :-)
I have directory with content (example)
/dir1/a/b/c/file1
/dir1/a/b/c/file2
/dir1/a/d/file3
/dir1/a/e/file4
/dir1/f/dir3/
/dir1/f/dir4/
...
I have list of files and directories, which can be removed - for example file1,file3 and dir3
I would like to move(move, not copy nor tar them - files are large and i need to do it in short time) them to another directory /dir2 (on the same filesystem), but - preserving subdirectories:
/dir1/a/b/c/file1 -> /dir2/a/b/c/file1
/dir1/a/d/file3 -> /dir2/a/d/file3
/dir1/f/dir3/ -> /dir2/f/dir3/
Is there any better way than for each file and directory(for directories skipping last part) create directory in dir2(using mkdir -p/install -d) and then moving it into?
one of simplest solutions is using rsync, with list of files in
--include-from, and with --remove-source-files. But - it copy files, and then remove then - i need to avoid copying - for large files it
take too much time.
If you are comfortable with rsync, you can use it just to list the files and then process that list with this short shell script:
cd dir1
rsync --files-from list --list-only --no-implied-dirs . / |
while read mode size date time path
do
dest=$dir2/`dirname $path` # $dir2 must be an absolute path
mkdirhier $dest
mv $path $dest
done
I have tried this code with example you mentioned above and it worked okay.. Please test it before you use it. In second line, you have to put all file names in a plain text file and provide it's path. My file contents are shown below
#!/bin/ksh
c_file="Path_to_the_file_containing_list_for_movement"
while IFS= read v_line
do
v_fullfilepath=$(find $1 -name "$v_line")
v_dirname=$(dirname $v_fullfilepath)
v_target_path=${v_dirname/$1\//$2/}
mkdir -p "$v_target_path"
mv $v_fullfilepath $v_target_path
#echo $v_line " " $v_fullfilepath " " $v_dirname " " $v_target_path
done <"$c_file"
This was my file contents,
file1
file3
dir3
Supposed I have directory structure like
src/
src/a/
src/a/1.ocf
src/a/1.pdf
src/a/1.txt
src/b/
src/b/2.ocf
src/b/2.pdf
src/b/2.xls
src/c/
src/c/3.doc
src/c/3.ocf
src/c/3.txt
src/d/
Then, I just want to synchronize only files with extension *.txt. So, I tried to use command like:
#rsync -avvH --include="*/" --include="*.txt" --exclude="*" src/ dst/
sending incremental file list
./
a/
a/1.txt
b/
c/
c/3.txt
d/
Unfortunately, this command not only synchronize *.txt file but also all directory. I don't want directory 'b' and 'd' be synchronized because it not contain file *.txt
Is there simple way to do that?
The option you're looking for is -m to prune empty directories:
rsync -avvHm --include="*/" --include="*.txt" --exclude="*" src/ dst/
I have two directories structured as follows:
dir1/a/file1
dir1/a/b/file2
dir1/a/c/d/file3
and
dir2/a/file4
dir2/a/b/file5
dir2/a/c/d/file6
I want to copy all the files in the subdirectories under dir1 to dir2, but keep the files that are currently in dir2, in other words I want to resulting structure to look like:
dir2/a/file1
dir2/a/file4
dir2/a/b/file2
dir2/a/b/file5
dir2/a/c/d/file3
dir2/a/c/d/file6
Is there a simple way to do this using bash?
You could start with
cd dir1
cp -rpuv * ../dir2/
Before:
$ find dir2/
dir2/
dir2/a
dir2/a/file4
dir2/a/c
dir2/a/c/d
dir2/a/c/d/file6
dir2/a/b
dir2/a/b/file5
After:
$ find dir2/
dir2/
dir2/a
dir2/a/file1
dir2/a/file4
dir2/a/c
dir2/a/c/d
dir2/a/c/d/file3
dir2/a/c/d/file6
dir2/a/b
dir2/a/b/file2
dir2/a/b/file5
Note that -p preserves permissions, -v make copy verbose and -u only updates files (doing what the question suggests: keep the files already in dir2)
In bash I need to do this:
take all files in a directory
copy them into an existing directory
How do I do this? I tried cp -r t1 t2 (both t1 and t2 are existing directories, t1 has files in it) but it created a directory called t1 inside t2, I don't want that, I need the files in t1 to go directly inside t2. How do I do this?
What you want is:
cp -R t1/. t2/
The dot at the end tells it to copy the contents of the current directory, not the directory itself. This method also includes hidden files and folders.
cp dir1/* dir2
Or if you have directories inside dir1 that you'd want to copy as well
cp -r dir1/* dir2
If you want to copy something from one directory into the current directory, do this:
cp dir1/* .
This assumes you're not trying to copy hidden files.
Assuming t1 is the folder with files in it, and t2 is the empty directory. What you want is something like this:
sudo cp -R t1/* t2/
Bear in mind, for the first example, t1 and t2 have to be the full paths, or relative paths (based on where you are). If you want, you can navigate to the empty folder (t2) and do this:
sudo cp -R t1/* ./
Or you can navigate to the folder with files (t1) and do this:
sudo cp -R ./* t2/
Note: The * sign (or wildcard) stands for all files and folders. The -R flag means recursively (everything inside everything).
cp -R t1/ t2
The trailing slash on the source directory changes the semantics slightly, so it copies the contents but not the directory itself. It also avoids the problems with globbing and invisible files that Bertrand's answer has (copying t1/* misses invisible files, copying `t1/* t1/.*' copies t1/. and t1/.., which you don't want).
For inside some directory, this will be use full as it copy all contents from "folder1" to new directory "folder2" inside some directory.
$(pwd) will get path for current directory.
Notice the dot (.) after folder1 to get all contents inside folder1
cp -r $(pwd)/folder1/. $(pwd)/folder2
Nov, 2021 Update:
This code with Flag "-R" copies perfectly all the contents of "folder1" to existing "folder2":
cp -R folder1/. folder2
Flag "-R" copies symbolic links as well but Flag "-r" skips symbolic links so Flag "-R" is better than Flag "-r".
The latest GNU Grep 3.7:
-R, --dereference-recursive
For each directory operand, read and process all files in that directory,
recursively, following all symbolic links.
-r, --recursive
For each directory operand, read and process all files in that directory,
recursively. Follow symbolic links on the command line, but skip symlinks
that are encountered recursively. Note that if no file operand is given,
grep searches the working directory. This is the same as the
‘--directories=recurse’ option.
Depending on some details you might need to do something like this:
r=$(pwd)
case "$TARG" in
/*) p=$r;;
*) p="";;
esac
cd "$SRC" && cp -r . "$p/$TARG"
cd "$r"
... this basically changes to the SRC directory and copies it to the target, then returns back to whence ever you started.
The extra fussing is to handle relative or absolute targets.
(This doesn't rely on subtle semantics of the cp command itself ... about how it handles source specifications with or without a trailing / ... since I'm not sure those are stable, portable, and reliable beyond just GNU cp and I don't know if they'll continue to be so in the future).
the correct option should be -T. used with -r to copy recursively.
$ cp -r -T t1 t2