LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.

Notices


Reply
  Search this Thread
Old 04-05-2019, 12:37 PM   #1
dedec0
Senior Member
 
Registered: May 2007
Posts: 1,372

Rep: Reputation: 51
Question A command for making this organization from a dir with a lot of files?


Hello,

I have a directory called file.set which contains 1000 thousand files (the number may vary), and we may assume no subfolder exist. I want to organize these files in directories in new folders, with at most 50 files (number may also vary). These directories should be created inside file.set with names "001.050", "051.100", etc.

Do you know a command for this? Or writing a shell script is the best option?

Last edited by dedec0; 04-05-2019 at 12:43 PM.
 
Old 04-05-2019, 12:52 PM   #2
scasey
LQ Veteran
 
Registered: Feb 2013
Location: Tucson, AZ, USA
Distribution: CentOS 7.9.2009
Posts: 5,727

Rep: Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211
I think you'd need to write a script to do that using mkdir and mv commands.
 
1 members found this post helpful.
Old 04-05-2019, 02:08 PM   #3
dedec0
Senior Member
 
Registered: May 2007
Posts: 1,372

Original Poster
Rep: Reputation: 51
Bash array with all files

I am creating a script now using Bash. I know (and have used before) that I can create a 'for' like this, to iterate on each file on a dir, ordered by name:

Code:
# list the $path dir
for fileName in $path/*; do
    echo $fileName
done
This 'for' is not appropriate for the algorithm i am using, though.

How do I obtain an array with each file in a position?

files=$path/*

and

files="$path/*"

do not work.

Or my problem is how i am trying to access the file names? With:

Code:
echo -e "mv $files[$n] $dest"         # where n is a var with a number
 
Old 04-05-2019, 03:30 PM   #4
dedec0
Senior Member
 
Registered: May 2007
Posts: 1,372

Original Poster
Rep: Reputation: 51
Question

Quote:
Originally Posted by dedec0 View Post
I am creating a script now using Bash. I know (and have used before) that I can create a 'for' like this, to iterate on each file on a dir, ordered by name:

Code:
# list the $path dir
for fileName in $path/*; do
    echo $fileName
done
This 'for' is not appropriate for the algorithm i am using, though.

How do I obtain an array with each file in a position?

files=$path/*

and

files="$path/*"

do not work.

Or my problem is how i am trying to access the file names? With:

Code:
echo -e "mv $files[$n] $dest"         # where n is a var with a number
Is there something better than navigating throw all files, building an array, like

Code:
arqs=()
for i in $dir/*; do
    arqs+=("$i")
done
does?
 
Old 04-05-2019, 05:25 PM   #5
scasey
LQ Veteran
 
Registered: Feb 2013
Location: Tucson, AZ, USA
Distribution: CentOS 7.9.2009
Posts: 5,727

Rep: Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211
Nothing wrong with a for loop, IMO.
Assuming that $path is populated correctly:
Code:
for file in $(ls -1 $path/) ;do 
     echo $file
done
That's a -one, not a -ell
Note that $file only contains the name of the file itself.

On the other hand, I guess I don't really understand how your
Code:
for fileName in $path/*
even works at all...but my comment about the for loop stands...
It will iterate through the file names for you just fine.

Last edited by scasey; 04-05-2019 at 05:43 PM.
 
1 members found this post helpful.
Old 04-05-2019, 06:18 PM   #6
dedec0
Senior Member
 
Registered: May 2007
Posts: 1,372

Original Poster
Rep: Reputation: 51
Thumbs down A script version, but it has a problem with the last set of files

I have made a script. But it has a problem i could not solve, maybe you can help.

This is its code:

Code:
#!/bin/bash
#   org: Organiza uma pasta com vários arquivos, criando várias subpastas com
# um número máximo de arquivos

# Versão: 2019,04,05,19,25,00 UTC-3
# Version that only prints the commands that would be done

# Print help
ajuda()
{
    echo Uso:
    echo -e "\torg [pasta]\n"
    echo -e   "Argumento:\n"
    echo -e   "\t[pasta]\t\ta pasta que contém vários arquivos a serem organizados.\n\t"
    return
}

# Processa argumento, possivelmente decidindo o diretório escolhido
if  (( ($# == 0) )); then
    ajuda
    exit 0
fi
if (( $# == 1 )); then
    if  [[ $1 == '-h' ]] ||
	[[ $1 == '--help' ]] ||
        [[ $1 == '--ajuda' ]];
	then 
        ajuda
	exit 0
    else
	dir="$1"
    fi
else
    dir="."
fi
#echo dir=$dir

# There is no better way to make an array with each file in dir?
arqs=()
for i in $dir/*; do
    arqs+=("$i")
done
#numArqs=${#arqs[@]}
#echo $numArqs arquivos
#arqs=$dir/*

n=0 				# In each folder, the number of a file
#qPorPasta=50;			# Files per dir (max)
qPorPasta=5;			# Files per dir (max)

#echo $qPorPasta
max=$qPorPasta
for (( max=qPorPasta; max<${#arqs[@]}; max+=qPorPasta )); do
    dest=`printf "%03i" $n`
    dest="$dest."
    dest="$dest"`printf "%03i" $max`
    #echo dest = \"$dest\"
    echo mkdir $dest
    #mkdir $dest
    for((; n<max; n++)); do
	if [[ $n -lt ${#arqs[@]} ]]; then
	    echo -e "mv ${arqs[n]} $dest"
	    #mv ${arqs[n]} $dest
	else
	    echo max=$max
	    for(( max+=qPorPasta; n<max; n++)); do
		if [[ $n -lt ${#arqs[@]} ]]; then
		    echo -e "mv ${arqs[n]} $dest"
		    #mv ${arqs[n]} $dest
		fi
	    done
	    break 3;
	fi
    done
done

exit 0
And these commands may help you making a test like mine:

Code:
cd /dev/shm mkdir t; cd t;
# 23 files from '00' to '22':
for (( i=0; i<23; i++)); do touch `printf "%02d" $i`; done
Executing the script in the t dir does not move the last set of files. The output (which would be the commands done) is this:

Code:
/dev/shm/org .    # 'org' is the script
mkdir 000.005
mv ./00 000.005
mv ./01 000.005
mv ./02 000.005
mv ./03 000.005
mv ./04 000.005
mkdir 005.010
mv ./05 005.010
mv ./06 005.010
mv ./07 005.010
mv ./08 005.010
mv ./09 005.010
mkdir 010.015
mv ./10 010.015
mv ./11 010.015
mv ./12 010.015
mv ./13 010.015
mv ./14 010.015
mkdir 015.020
mv ./15 015.020
mv ./16 015.020
mv ./17 015.020
mv ./18 015.020
mv ./19 015.020
 
Old 04-05-2019, 06:34 PM   #7
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
this is a script I use to devide up x amount of dirs and putting all of the parent sud-directores into a set up to 4 other parent dirs.


Code:
#!/bin/bash


working_dir=/run/media/userx/1TB/ARedoneMusic_Sorted

move=( /run/media/userx/1TB/Music_2_do1 /run/media/userx/1TB/Music_2_do2 /run/media/userx/1TB/Music_2_do3 /run/media/userx/1TB/Music_2_do4 )
#move=( /run/media/userx/2TBInternal/Music_2_do1 /run/media/userx/2TBInternal/Music_2_do2 /run/media/userx/2TBInternal/Music_2_do3 /run/media/userx/2TBInternal/Music_2_do4 )
t=0



#remove empty directories from working working_dir

while read d ;
do
  rmdir -v "$d"
done <<< "$(find "$working_dir" -type d)"



mkdir -pv /run/media/userx/1TB/Music_2_do1
mkdir -pv /run/media/userx/1TB/Music_2_do2
mkdir -pv /run/media/userx/1TB/Music_2_do3
mkdir -pv /run/media/userx/1TB/Music_2_do4



echo
totalDir="$(find "$working_dir"  -maxdepth 1 -mindepth 1   -type d  | wc -l)"

divDir=$(($totalDir / 4))

echo "Total DIr         Div/4
$totalDir               $divDir"

countDn=0

    while read f
    do
                    if  [[ $countDn -le $divDir ]] ; then
                    {
                        mv -f  "$f" "${move[$t]}"
                        ((countDn++))
                    }
                    fi

        echo "t $t"

        [[ $countDn = $divDir ]] && { ((t++)) ; countDn=0 ; }

     [[ $t -eq 4 ]] &&
     { echo "$t $countDn $divDir" ; exit ; }



done <<< "$(find "$working_dir" -maxdepth 1 -mindepth 1 -type d)"
basically what you want to do is something similar like run a loop and a count on files, if x amount of files reached then create a new dir then start putting files into that one, reset count then loop until same x amount reached then create another dir then repeat process.

Code:
#!/bin/bash

working_dir=/whatever/
move2=/destanation->

count=0
newDir=0
xamount=100

#create 1st dir
mkdir "$move2"_"$newDir"

while read f
do

mv -f "$f" "$move2"_"$newdir"
((count++))

#reset count add 1 to dir name, create new dir
[[ "$count" -eq $xamount ]] && { count=0 ; ((newDir++)) ; mkdir "$move2"_"$newDir" ; }

done <<<"$(find "$working_dir" -type f )"
adds a number to end of whatever you name your dirs you want your files in.

not tested.


rereading that last post, question?
you are reading all of the files first then putting the file path/name into an array first, then using that array to get the x amount of files and moving them into a different directory then getting the next set of files and doing the same until you're out of files?

the way I wrote it, it just going though the dir, putting the files into dir created dynamically as it loops through the files, when it gets to the end it stops no matter how many files left because it goes until eof.

Last edited by BW-userx; 04-05-2019 at 07:00 PM.
 
Old 04-05-2019, 06:34 PM   #8
scasey
LQ Veteran
 
Registered: Feb 2013
Location: Tucson, AZ, USA
Distribution: CentOS 7.9.2009
Posts: 5,727

Rep: Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211
You're processing only when the count is less than the number of entries in the array, so you're not processing the last entry. Try:
Code:
for (( max=qPorPasta; max<${#arqs[@]+1}; max+=qPorPasta )); do
or
Code:
for (( max=qPorPasta; max<=${#arqs[@]}; max+=qPorPasta )); do
Not sure if that's the only issue.
 
Old 04-05-2019, 10:54 PM   #9
allend
LQ 5k Club
 
Registered: Oct 2003
Location: Melbourne
Distribution: Slackware64-15.0
Posts: 6,371

Rep: Reputation: 2750Reputation: 2750Reputation: 2750Reputation: 2750Reputation: 2750Reputation: 2750Reputation: 2750Reputation: 2750Reputation: 2750Reputation: 2750Reputation: 2750
I would suggest adding a counter to the loop so that a remainder test can be used for branching.
Code:
j=50
for i in {1..501}; do
  if (( $i % 50 == 0 )); then
    j=$(( $i + 50 ))
  elif (( $i % 50 == 1 )); then
    echo
    echo "$i-$j"
    # make next directory here
  fi
  echo -n "$i "
done
 
  


Reply



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
copy files only in dir 2 that are not also in dir 1 into a new dir jr_bob_dobbs Linux - General 6 03-22-2018 10:35 AM
copying files from home dir to another dir from another dir in a lower dir chomito44 Linux - General 5 10-19-2013 06:18 PM
Move files contained in source dir to destination dir, but not source dir itself unixunderground Linux - Software 3 09-20-2013 11:17 AM
tar dir and sub dir removing files but not existing not empty dir j-me Linux - General 2 08-12-2013 11:37 AM
Command to display /dir, /dir/sub, /dir/sub/files knockout_artist Linux - Newbie 9 10-25-2007 02:57 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software

All times are GMT -5. The time now is 05:42 PM.

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
Open Source Consulting | Domain Registration