How to move files from subdirectory to a directory using a for loop - linux

How do I move a file 1 directory up using loop? Can someone maybe help me out?
I tried this:
for dir in */*/
do mv "$dir"/*
done

Like that:
for dir in */*/
do
echo mv "$dir"* "${dir%/*/}" # Drop the echo after tested it
done
Note that this will move all files and directories under $dir to the parent directory of the $dir. If you want to move a specific file, replace "$dir"* with "$dir"file where file is the filename of the specific file. Also be very careful where and how you use this code after echo removed (running in the wrong directory would be catastrophic)

Related

Remove directory structure, but keep directory contents

I meant to run this code inside a specific directory within my home directory, but accidentally ran it in my home directory itself:
i=0; for f in *; do d=dir_$(printf %03d $((i/8+1))); mkdir -p $d; mv "$f" $d; let i++; done
Now all my files and directories have been grouped into separate directories. I need to remove this action, and restore my original organization. Is this possible?
Using shell expansion:
mv dir_*/* .
should move the content of all dir_ subdirectories back into the current one. For "hidden" files, if necessary, move dir_*/.*.

Linux Bash: Move multiple different files into same directory

As a rather novice Linux user, I can't seem to find how to do this.
I am trying to move unique files all in one directory into another directory.
Example:
$ ls
vehicle car.txt bicycle.txt airplane.html train.docx (more files)
I want car.txt, bicycle.txt, airplane.html, and train.docx inside vehicle.
Right now I do this by moving the files individually:
$ mv car.txt vehicle
$ mv bicycle.txt vehicle
...
How can I do this in one line?
You can do
mv car.txt bicycle.txt vehicle/
(Note that the / above is unnecessary, I include it merely to ensure that vehicle is a directory.)
You can test this as follows:
cd #Move to home directory
mkdir temp #Make a temporary directory
touch a b c d #Make test (empty) files ('touch' also updates the modification date of an existing file to the current time)
ls #Verify everything is there
mv a b c d temp/ #Move files into temp
ls #See? They are gone.
ls temp/ #Oh, there they are!
rm -rf temp/ #DESTROY (Be very, very careful with this command)
Shorthand command to move all .txt file
You can try using a wildcard. In the code below, * will match all the files which have any name ending with .txt or .docx, and move them to the vehicle folder.
mv *.txt *.docx vehicle/
If you want to move specific files to a directory
mv car.txt bicycle.txt vehicle/
Edit: As mentioned in a comment, If you are moving files by hand, I suggest using mv -i ... which will warn you in case the destination file already exists, giving you a choice of not overwriting it. Other 'file destroyer' commands like cp & rm too have a -i option
mv command in linux allow us to move more than one file into another directory. All you have to do is write the name of each file you want to move, seperated by a space.
Following command will help you:
mv car.txt bicycle.txt airplane.html train.docx vehicle
or
mv car.txt bicycle.txt airplane.html train.docx vehicle/
both of them will work.
You can move multiple files to a specific directory by using mv command.
In your scenario it can be done by,
mv car.txt bicycle.txt airplane.html train.docx vehicle/
The point you must note is that the last entry is the destination and rest everything except mv is source.
One another scenario is that the destination is not present in our directory,then we must opt for absolute path in place of vehicles/.
Note: Absolute path always starts from / ,which means we are traversing from root directory.
I have written a small bash script that will move multiple files(matched using pattern) present in multiple directories(matched using pattern) to a single location using mv and find command in bash
#!/bin/bash
for i in $(find /path/info/*/*.fna -type f) # find files and return their path
do
mv -iv $i -t ~/path/to/destination/directory # move files
done
$() is for command substitution(in other words it expand the expression inside it)
/*/ wild card for matching any directory, you can replace this with any wild card expression
*.fna is for finding any file with.fna extension
-type f is for getting the full path info of the located file
-i in mv is for prompt before overwrite( extra caution in case the wild card exp was wrong)
-v for verbose
-t for destination
NOTE: the above flags are not mandatory
Hope this helps

How to create empty txt files in a directory reflecting files in another directory?

I need to do some testing and need the same file names as I have in directory /home/recordings in /home/testing folder.
For example, if i have a file recording01.mp4 in /home/recordings, i would want to have the an empty file recording01.txt or recording01.mp4 or in /home/testing
I understand I can use the following command?
for i in /home/recordings/*; do touch "$i"; done
Not sure how to specify extension or the destination directory in this case?
A simple addition of /home/testing/ to touch command will do it.
for i in /home/recordings/*; do
temp=`echo $i|cut -f3 -d'/'`
cd /home/testing/
touch "$temp";
cd ../..
done
I assume you are not in home directory and running this script file from anywhere else.
You can also do this without a loop
find /home/recordings/ -type f -printf /home/testing/%f'\n' | xargs -n1 touch
Try this:
for i in /home/recordings/*; do touch "/home/testing/$i"; done
You need only specify absolute paths and things will work fine. A bunch of 0-length files are created, their names corresponding to those in /home/recordings.

Using for loop to move files from subdirectories to parent directories

I just made the switch to linux and I am trying to write my first bash script. I have a folder that contains numerous folders, all with subfolders containing files. Something like:
MainFolder
Folder1
Sub1 (Contains many files)
Sub2 (Contains many files)
Folder2
Sub1 (Contains many files)
Sub2 (Contains many files)
.
.
.
I want to move all the files contained in the sub-folders to the their parent folders. My first instinct is to try and write a for-loop. I was able to do one folder at a time with the command:
mv MainFolder/Folder1/*/* MainFolder/Folder1/
But I was hoping to write a bash script to loop over all the folders in the main directory. Here is what I have so far:
#!/bin/bash
dir1="/pathto/MainFolder"
subs= ls $dir1
for i in $subs; do
mv "$dir1/$i/*/*" "$dir1/$i/"
done
This, obviously, does not work, but I do not understand where I am going wrong.
I also tried:
mv MainFolder/*/*/* MainFolder/*/
with pretty disastrous results. Once I get the file move working properly, I would also like to delete the old sub folders within the loop.
Small change. change
subs=ls $dir1
to
subs=`ls $dir1`
Notice the backquotes. Backquotes actually execute the bash command and return the result. If you issue echo $subs after the line, you'll find that it correctly lists folder1, folder2.
Second small change is to remove double quotes in the mv command. Change them to
mv $dir1/$i/*/* $dir1/$i
Double quotes take literal file names while removing quotes takes the recursive directory pattern.
After that, your initial for loop is indeed correct. It will move everything from sub1 and sub2 to folder1 etc.
Yes - this is working solution
#!/bin/bash
mainDir="$(dirname $(realpath $0))/store/media"
subs=`ls $mainDir`
for i in $subs; do
if [[ -d "$mainDir/$i" ]]; then
mv "$mainDir/$i"/* "$mainDir/"
rm -rf "$mainDir/$i"
fi
done
!/bin/bash
dir1="/pathto/MainFolder"
subs=ls $dir1
for i in $subs; do
mv $dir1/$i// $dir1/$i
done

mv: cannot overwrite directory with non-directory

Is it possible to get around this problem?
I have a situation where I need to move some files to 1 directory below.
/a/b/c/d/e/f/g
problem is that the filename inside g/ directory is the same as the directory name
and I receive the following error:
mv: cannot overwrite directory `../297534' with non-directory
Example:
/home/user/data/doc/version/3766/297534 is a directory, inside there is a also a file named 297534
so I need to move this file to be inside /home/user/data/doc/version/3766
Command
This is what I am running: (in a for loop)
cd /home/user/data/doc/version/3766/297534
mv * ../
You can't force mv to overwrite a directory with a file with the same name. You'll need to remove that file before you use your mv command.
Add one more layer in your loop.
Replace mv * ../ with
for f in `ls`; do rm -rf ../$f; mv $f ..; done
This will ensure that any conflict will be deleted first, assuming that you don't care about the directory you're overwriting.
Note that this will blow up if you happen to have a file inside the current directory which matches the current directory's name. For example, if you're in /home/user/data/doc/version/3766/297534 and you're trying to move a directory called 297534 up. One workaround to this is to add a long suffix to every file, so there's little chance of a match
for f in `ls`; do mv $f ../${f}_abcdefg; done

Resources