how to move only files to subdirectory in linux - linux

I would like to create a sub directory and move only files from the directory dir to the new created sub directory. I tried this:
$ mkdir dir/subdir ----> subdir is created
$ mv -if dir/* dir/subdir -----> all files and directories in dir will be moved into dir/subdir
How to move only files to subdirectory?

You can use find(1).
$ mkdir dir/subdir
$ find dir -maxdepth 1 -type f -exec mv {} dir/subdir \;

$ find dir -maxdepth 1 -type f -exec mv {} dir/subdir \;

Related

create a new directory under all directories using single command : 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.

How to delete files under subdirectories but not deleting subdirectories themselves in linux

I have the following directory structure:
/archive/file1.csv
/archive/file2.csv
/archive/myfile/my.txt
/archive/yourfile/your.txt
I want to delete all files under /archive but not its subfolders, so after deletion, the directory structure should look like:
/archive/
/archive/myfile/
/archive/yourfile/
I have tried the following two commands, but the files under the subfolders are not deleted (ie. my.txt and your.txt), anyone know why ?
find -L /archive ! -type d -exec rm -rfv {} +
find -L /archive -type f -exec rm -rfv {} +
use find
$ find . ! -type d -delete
make sure you're in the right path.

MOVING Files and place them into folders accordingly to text file

I need to move files from ORIGIN and place them to DESTINATION accordingly to the information contained in text file "toto.txt"
I do NOT know how to code the part which says:
place these files accordingly with the information contained in toto.txt which states
the sub-folder structure on DESTINATION folder"
toto.txt conatins the folder structure of ORIGIN and the files must be moved accordingly to DESTINATION but with the original folder structure location.
# My working Paths
MY_DIR1="/media/nss/MBVOL1/TEST/ORIGIN"
MY_DIR2="/media/nss/MBVOL1/TEST/DESTINATION"
# Flag files older than 1 day and list their name\full path to “TOTO” text file
echo "REPORT Created"
cd $MY_DIR1 && find . -mindepth 0 -maxdepth 40 -mtime +1 -type f > toto.txt
cp $MY_DIR1/toto.txt /$MY_DIR2
# Flag files older than 1 day then MOVE file to “DESTINATION” Folder
echo "FILES Moved"
find $MY_DIR1 -mindepth 0 -maxdepth 400 -type f -mtime +14 -exec mv '{}' $MY_DIR2 \;
Try this:
cd "$MY_DIR1"
# Duplicate directory structure
find . -type d -exec mkdir -p "$MY_DIR2"/{} \;
# move files older than 1 day
find . -type f -mtime +1 -exec mv {} "$MY_DIR2"/{} \;
You can combine them into one command:
find . -type d -exec mkdir -p "$MY_DIR2"/{} \; -o -type f -mtime +1 -exec mv {} "$MY_DIR2"/{} \;
Use something like this...
cat ${MY_DIR2}/toto.txt | while read FILE ; do
mv -v "${MY_DIR1}/${FILE}" "${MY_DIR2}"
done

How to change file and directory names with find?

I changed project name and now I have many files an directories with old name. How to replace these names with find?
find . -name "*old_name*" -exec ???
This find should work for you:
find . -name "old_name" -execdir mv "{}" new_name +
This will find files with the name old_name from the current dir in all sub directories and rename them to new_name.
Below is what I have used in the past. The biggest gotcha is the RHEL rename (c) vs Debian rename (perl) - They take different options. The example below uses RHEL c based rename command. Remove the '-type f' to also rename the directories.
find . -type f -name "*old_name*" -print0 | xargs -0 -I {} /usr/bin/rename "old_name" "new_name" {}
newname="myfile.sh"; for files in $(find Doc2/scripts/ -name gw_watch_err.sh); do echo $files; dir=${files%/*}; cfile=${files##*/}; echo "$dir -- $cfile"; echo "mv $cfile $newname"; done
Doc2/scripts/gateway/gw_watch_err.sh
Doc2/scripts/gateway -- gw_watch_err.sh
mv gw_watch_err.sh myfile.sh
you could also add:
find . -maxdepth 1 -iname file
where maxdepth will ensure you dont need to worry about sub folders and iname means case sensitive
Ok, my solution:
find . -name "*old_name*" -exec rename 's/old_name/new_name/g' {} \;
But this works for directories which name not contain "old_name", otherwise find say for example:
find: `./old_name': No such file or directory
Because it trying search in "old_name" directory, and the directory is already a "new_name"
renaming multiple directories with find: how to catch the catches
here's a little story on how to rename multiple files with find, but for the impatient I first put the proper command for your specific problem here:
find -depth -name "old name" -execdir mv -iv {} "new name" \;
and for the patient ones, a few misadventures with find, restricting changes to directories only:
we want to rename all directories named old dir into new dir recursively inside a current directory
we create an empty directory inside which we create a simple directory hierarchy:
$ cd $(mktemp -d) && mkdir -p "old dir" "subdir/old dir/old dir"
$ find | sort
.
./old dir
./subdir
./subdir/old dir
./subdir/old dir/old dir
the use of of the -exec action works only for a rename directly under a current directory, which you can see by dry-running a rename command (note that the shell doesn't output the quotes, which is not an error):
$ find -type d -name "old dir" -exec echo mv -iv {} "new dir" \;
mv -iv ./subdir/old dir new dir
mv -iv ./subdir/old dir/old dir new dir
mv -iv ./old dir new dir
note that only the first rename command would work as expected
the use of the -execdir action runs the command from the subdirectory containing the matched directory:
$ find -type d -name "old dir" -execdir echo mv -iv {} "new dir" \;
mv -iv ./old dir new dir
mv -iv ./old dir new dir
mv -iv ./old dir new dir
which seems fine as the rename commands are run in the matching directories, so we no longer dry-run:
$ find -type d -name "old dir" -execdir mv -iv {} "new dir" \;
'./old dir' -> 'new dir'
find: ‘./subdir/old dir’: No such file or directory
'./old dir' -> 'new dir'
find: ‘./old dir’: No such file or directory
$ find | sort
.
./new dir
./subdir
./subdir/new dir
./subdir/new dir/old dir
the problem is that the old dir is renamed new dir and find cannot descend further inside a renamed directory
a solution is to process each directory's contents before the directory itself, which is precisely what the -depth option does:
$ cd $(mktemp -d) && mkdir -p "old dir" "subdir/old dir/old dir"
$ find -depth -type d -name "old dir" -execdir mv -iv {} "new dir" \;
'./old dir' -> 'new dir'
'./old dir' -> 'new dir'
'./old dir' -> 'new dir'
$ find | sort
.
./new dir
./subdir
./subdir/new dir
./subdir/new dir/new dir
1. First, backup your directories and files
The following Bash code run on my OS X and Ubuntu boxes.
2. Rename the directories from old_dir to new_dir:
for d in $(find . -maxdepath X -type d -name 'old_dir'); do mv $d "$(dirname $d)/new_dir"; done
X is a number used to specify the depth of replacing old_dir
3. Rename the files from old_file to new_file:
for f in $(find . -type f -name 'old_file'); do mv $f "$(dirname $f)/new_file"; done
Don't care about #Benjamin W. and #ghoti them one for his ForMatted code and #ghoti try to orient the question to his Pitfalls.
Hi, #Benjamin W. what about this new post? and #ghoti did you run the above code incorrectly on your machine? If the code can't work just let me know or post a question pls, and if you had a better one pls post here let we know.

Bash script unrar then rename with dir name

I want to rename files in a dir then change the file name base on the dir name this is what I had but it's not quite working
find . -type d | while read dir
do
cd "$dir"
find . -name \*.rar -exec unrar x '{}' \;
find . -name \*.avi -exec mv '{}' "$dir.avi" \;
cd ..
done
root/directory.1.with.rar.in/
root/directory.2.with.rar.in/
root/directory.2.with.rar.in/
root/directory.2.with.rar.in/
root/directory.2.with.rar.in/
I want all the rar in the Directory to be extracted in root then renamed with the name of the directory it was extracted from.

Resources