-1

In a directory I have files with the names:

01.txt 02.txt 03.txt

In the same directory are folders with the names:

01.abc 02.def 03.ghi

I need a command to copy the files to the folders one by one, so that 01.txt is in 01.abc, 02.txt is in 02.def and 03.txt is in 03.ghi. The command should not consider the names of the folders but fill the folders with the files top down (one file to each folder).

Many thanks!

Edit 1:

I have changed the code from Move files to multiple folders [closed] as follows:

#!/bin/bash

LISTFILESCMD='ls *.txt' 
FQUANTITY=1
FOLDERLIST=`seq -w 1 3`

for FOLDER in $FOLDERLIST; do mv `$LISTFILESCMD | head -n $FQUANTITY`   $FOLDER; done

The result is, that the 3 files are in the 3rd folder.

Edit 2:

No, with FQUANTITY=3 the files go in the 1st folder.

With FQUANTITY=1 the script above works. But it doesn't work right, if the filenames or the foldernames contain spaces.

I have made a second script, which also works with spaces in filenames, but only if the filenames contain a dot, and this script doesn't work, if the foldernames contain spaces. I would like to know, how to make it work also with spaces in foldernames and/or without dots in filenames:

#!/bin/bash

array1=(*/) # folder
array2=(*.*) # file

for ((i=0;i<${#array2[@]};++i)); do
    mv "${array2[i]}" "${array1[i]}"
done

Thanks!

  • 2
    What did you try? What is your use-case? I'm asking, because for 3 files you could potentially do this manually... – pLumo Jul 8 at 11:33
  • There are more files in the directory. The files here are just an example. The use-case is to copy the files with one click. – elli Jul 8 at 11:44
  • What about my first question? – pLumo Jul 8 at 11:44
  • 1
    Use array variables: set one to the files and the another to the folders. Loop over them. – L. Scott Johnson Jul 8 at 11:47
  • 1
    As to the "tried to ask a question" part, see unix.stackexchange.com/help/how-to-ask – L. Scott Johnson Jul 8 at 11:48
0

The result is, that the 3 files are in the 3rd folder.

You mean: the 1st folder? Why you choose fquantity=3 if you have only 3 files overall? It is files-per-folder quantity!

I tested that for loop, and it works so far. You have to choose the right "quantity" to distribute your files evenly into the dirs.

Your Q is really a bit hard to understand, with the file names you give and the quantity. And: 01.txt belongs into 01.abc, "but the names should not be considered".

You have, say, 3000 files that should be moved into 17 folders. Or is it x folders each with max. of 200 files? This would be the first step, simple math and a loop with a counter.

Then come the questions of "robustness" (whitespace) and performance, and how to use standard commands to simplify the "program".

Your example:

for FOLDER in $FOLDERLIST; do mv `$LISTFILESCMD | head -n $FQUANTITY`   $FOLDER; done

is elegant in some way, because it doesn't need a filelist: it reads in the remaining (unmoved) files. And it should be fast enough, because you fill every folder only once, with one big mv command.

By choosing the right arg to head (fquantity) I could mv 7 files to 3 dirs as I want --- I thought I wanted 3-3-1. But if I choose quantity "7", I get all 7 files in the FIRST dir. With "1" I get 1-1-1, and four unmoved files. Ideal would be 3-2-2...so maybe the math involved is not even sooo simple.

But: a filename with whitespace is not moved, and it's parts are not found by mv. The author was surprised as it seems and commented: oh, must be a whitespace problem.

  • Yes, you're right. The files go into folder 1. And also, my question is hard to understand. I wanted to say, that the files should not be resorted by the command. Thank you for your answer and the detailed explanation! – elli Aug 7 at 18:00
0

Your solution with arrays should work even with files containing spaces, since you did quote the expansions properly. You might have trouble with filenames starting with dashes, though, use mv -- file dir/ to prevent that (or put ./ in front of the globs: ./* instead of * etc.).

As for picking only files, I don't think there's a way to do it directly in Bash (zsh could do it, though). But we can just pick a list of everything and filter the regular files from it:

#!/bin/bash

dirs=(*/)   # directories
tmp=(*)     # everything
files=()    # files

for f in "${tmp[@]}"; do
    if [ -f "$f" ]; then
        files+=("$f")
    fi
done

for ((i=0 ; i < ${#dirs[@]} ; ++i)); do
    mv -- "${files[i]}" "${dirs[i]}"
done
  • This works perfect. Thank you very much! – elli Aug 8 at 14:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.