LinuxQuestions.org
Latest LQ Deal: Complete CCNA, CCNP & Red Hat Certification Training Bundle
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 12-22-2011, 04:40 PM   #1
Nix
LQ Newbie
 
Registered: Dec 2011
Posts: 6

Rep: Reputation: Disabled
Move all files not in a directory into a subdirectory named for each given file


Hi

Looking for some help with a script that will take all files in any given root folder (which are not already in a folder) and put them into separate folders with the name of each given file.

Any ideas?

Thank you!

Dan
 
Old 12-22-2011, 05:46 PM   #2
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.9, Centos 7.3
Posts: 17,362

Rep: Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377
Can you show us what you've got so far; are you using bash?
You'll want these links
http://rute.2038bug.com/index.html.gz
http://tldp.org/LDP/Bash-Beginners-G...tml/index.html
http://www.tldp.org/LDP/abs/html/

You'll prob want the file tests http://tldp.org/LDP/abs/html/fto.html, conditionals http://tldp.org/LDP/Bash-Beginners-G...l/chap_07.html, loops http://tldp.org/LDP/Bash-Beginners-G...l/chap_09.html
 
1 members found this post helpful.
Old 12-22-2011, 05:49 PM   #3
Nix
LQ Newbie
 
Registered: Dec 2011
Posts: 6

Original Poster
Rep: Reputation: Disabled
Hey Chris!

Thank you for helping

I am reading around on tldp.org trying to figure out a way to go about this

a few things:

I am not a programmer or a scripter, i just found something i want to do with some organization of files and no conventional tool to do it so I am making a scripting attempt

so thus far, i have a blank script page with just some pseudo instructions for one way to go about it.

I really am not sure where to start...

Still looking up the commands that will really work with this kind of thing
 
Old 12-22-2011, 05:56 PM   #4
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.9, Centos 7.3
Posts: 17,362

Rep: Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377
Well, bookmark the main links I gave you and read the Rute Tutorial one (v good) & reference the other 2.
In particular, as mentioned, the specific techniques mentioned in the last 3 links.
A good tip when starting out; don't try to write the entire script in one go, break it down into stages and test each one.
For example, in your case I'd start with trying to find all entries in the root dir and determine what type they are (hint: see file tests link )

Easy to search for cmds here http://linux.die.net/man/

You'll prob want find cmd http://linux.die.net/man/1/find or maybe ls http://linux.die.net/man/1/ls
 
1 members found this post helpful.
Old 12-22-2011, 05:59 PM   #5
Nix
LQ Newbie
 
Registered: Dec 2011
Posts: 6

Original Poster
Rep: Reputation: Disabled
yea that's what im doing, just going piece by piece... identify if it's a file or a directory... then basically capture the directory into an array and then process down the array creating a folder for every found file's name... once that's done... check to see if a file's corresponding directory name exists and if it does then move the file into the directory?


Is that a good approach?

Sounds simple enough tho im not sure how to deal with the array... and still working on just getting an output of all the regular non directory files in a folder.

Thanks for your links, looking through them
 
Old 12-22-2011, 06:10 PM   #6
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.9, Centos 7.3
Posts: 17,362

Rep: Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377Reputation: 2377
Don't need the array, just process each entry as you retrieve it; see loops link
Re dir create; check return code of dir create as you do it; no need to scan twice; google ' bash $? ' http://tldp.org/LDP/abs/html/internalvariables.html http://tille.garrels.be/training/bas...ml#table_03_03

PS: FYI *nix is case sensitive!
Also, don't put spaces in filenames; its syntactically valid (unfortunately), but by default its usually interpreted as a parameter separator; you can imagine the trouble that causes ...

Last edited by chrism01; 12-22-2011 at 06:23 PM.
 
1 members found this post helpful.
Old 12-22-2011, 06:38 PM   #7
Nix
LQ Newbie
 
Registered: Dec 2011
Posts: 6

Original Poster
Rep: Reputation: Disabled
o_O

Last edited by Nix; 12-23-2011 at 03:53 AM.
 
Old 12-22-2011, 07:25 PM   #8
Nix
LQ Newbie
 
Registered: Dec 2011
Posts: 6

Original Poster
Rep: Reputation: Disabled
This is what i've pieced together so far

Code:
for FILE in *.{avi}
do
  DIR="{$FILE%.*}
  mkdir -p $DIR
  mv $FILE $DIR
done
doesn't work of course

Last edited by Nix; 12-23-2011 at 03:50 PM. Reason: adhering to forum standards for posting content
 
Old 12-23-2011, 08:22 AM   #9
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959
Please use [code][/code] tags around your code and data, to preserve formatting and to improve readability.

And just saying it "doesn't work" is not very helpful. In what way doesn't it work? What results and error messages do you get?

You have the basic idea right, but your implementation of it is broken. You have three syntax errors in your short loop. Look carefully at these two parts:

Code:
*.{avi}
"{$FILE%.*}

As a new scripter, I think you'll get a better understanding if you start with the Bash Guide, rather than the tldp stuff. It presents all the basic concepts in an easy-to-read manner:

http://mywiki.wooledge.org/BashGuide

And when you're finished, continue on to these pages from the same site:

http://mywiki.wooledge.org/Arguments
http://mywiki.wooledge.org/WordSplitting
http://mywiki.wooledge.org/Quotes

http://mywiki.wooledge.org/glob
http://mywiki.wooledge.org/BashFAQ/073
http://mywiki.wooledge.org/BashFAQ/100

http://mywiki.wooledge.org/BashPitfalls
http://mywiki.wooledge.org/BashFAQ

PS: There's nothing wrong with storing the names in an array first either. It's just another way to go about it. In this case though, it adds an unnecessary step.

Last edited by David the H.; 12-23-2011 at 08:25 AM. Reason: minor fixes
 
1 members found this post helpful.
Old 12-23-2011, 05:29 PM   #10
Nix
LQ Newbie
 
Registered: Dec 2011
Posts: 6

Original Poster
Rep: Reputation: Disabled
David, thank you for your well rounded follow up comment.

I will be sure to make use of all the resources you have outlined as well as uphold community principals for posting.

Here is what I have learned in one day from reading around on the net. My first successful shell script!
No Hello World or anything. Straight to this

We have gone from:

Code:
for FILE in *.{avi}
do
  DIR="{$FILE%.*}
  mkdir -p $DIR
  mv $FILE $DIR
done
To my final working version of this!

Code:
#!/bin/bash

clear

echo "################################################################"
echo "Hello," $USER
echo "Bash version is" $BASH_VERSION
echo "Current directory is" $PWD
echo "Changing directory..."
cd /home/admin/Test
echo "Working directory changed to:" $PWD
echo "################################################################"

# save and change IFS
OLDIFS=$IFS
IFS=$'\n'
 
for FILE in *
do
  DIR="$FILE"
echo "Processing" $FILE
  mkdir ${DIR%.*}
echo "Creating Directory For" ${FILE%.*}
  mv $FILE ${DIR%.*}
echo "Moving $FILE into Directory"
echo "Processing next file..."
done
I realize this is far from perfect, however it is working for me. and I will further play with it to refine input variables for directory selection, and maybe some error handling, or for setting the files to include/exclude // extensions.. never know. I am sure I will use this again!

Thank you all for your suggestions and assistance!
 
Old 12-24-2011, 01:40 PM   #11
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959
That's certainly better. Good work!

There are a couple of things you should try to ingrain into your coding behavior from the outset, however.

1) Learn to always quote your variable expansions, especially when working with filenames. I know you set IFS to newline this time, so this script is safe from word-splitting, but you should still get into the habit of doing it by default. It's just that important.

Longer strings like this can and should be quoted as a single unit:

Code:
echo "Processing" $FILE
#better:
echo "Processing $FILE"
Environment variables are generally all upper-case, so it's a good idea to give your own script variables lowercase or mixed case names to differentiate them. Not really an important point, but it is a traditional practice.

Oh, and you really don't need to back-up the old IFS setting in a script unless you have a need to revert back to it later on.

2) If you haven't seen it yet, the last page of the Guide has a section on formatting and readability. Properly indenting and blocking your code makes for code that's more readable and easily debuggable.

Good commenting is important too. What your script is doing may seem obvious to you now, but I guarantee that in a few years you'll look back on some of your old code and wonder what the heck that's supposed to be doing (and possibly what you were high on when you wrote it ). Learn to comment as you code.

And while not absolutely necessary, a lot of us think the "do/then" keywords read better when placed on the same line as the "for/while/until/if" keywords they're paired with.

So here's how I would do your main loop from above:
Code:
for file in *; do	# I thought you wanted to use *.avi here?
	echo "Processing $file"

	echo "Creating Directory $dir"
	dir="${file%.*}"
	mkdir -p "$dir"

	echo "Moving $file into $dir"
	mv -t "$dir" "$file" 

	echo "Processing next file..."
done

("mkdir -p" has the side-effect of it not erroring if the dirname already exists, and explicitly defining the target directory with "mv -t" is safer than depending on it simply using the last argument. Also, in this case the echo commands act pretty well as comments, so we don't really need to explain it any further. You could however just use the -v option in the above commands instead, and skip the echos. )
 
1 members found this post helpful.
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
move all files in current directory into a subdirectory in the current directory jakykong Linux - Newbie 8 07-16-2013 11:46 PM
Accessing files of a subdirectory whose parent directory is in a different partition. ajitht1986 Linux - General 1 06-10-2011 07:54 AM
Advice? Best way to move files daily to a daily "date" named directory ziphem Linux - Newbie 2 04-15-2007 08:03 AM
script for deleting .dat files which > 5 mb from a directory and its subdirectory anindyabhattacharjee Linux - Enterprise 2 01-15-2007 11:38 PM
How to move files from a subdirectory to another? Akhran Linux - Newbie 4 04-07-2006 05:41 AM


All times are GMT -5. The time now is 04:44 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration