1

I have several files with different extensions and directories with the same basename, like this example.

FileA.txt
FileA.html
FileA.directory/

FileB.txt
FileB.html
FileB.directory/

FileC.txt
FileC.html
FileC.directory/

And i would like to create a for-loop for which i can move all files to their corresponding directory based on their basename. Resulting in the following

FileA.directory/FileA.txt
FileA.directory/FileA.html

FileB.directory/FileB.txt
FileB.directory/FileB.html

FileC.directory/FileC.txt
FileC.directory/FileC.html

I've tried to find several suggestion which are kind of similar to my problem on this page, like this example. But i can't find a completely similar question.

for dir in .*/
do
    for f in "$dir"*
    do
        base=${f#$dir}
        mv "$base.*" "$dir"
    done
done

However I can't get it to work.

3 Answers 3

1

Assuming the names of the files and directories follow the same naming convention in that they share some common grouping prefix followed by a dot, and assuming we don't know the filename suffixes of files or directories:

topdir=.

for dirname in "$topdir"/*/; do
    prefix=$( basename "$dirname" )  # $topdir/FileC.directory/ --> FileC.directory
    prefix=${prefix%%.*}             # FileC.directory          --> FileC

    for filename in "$topdir/$prefix".*; do
        if [ ! -d "$filename" ]; then
            mv -i "$filename" "$dirname"
        fi
    done
done

The outer loop iterates over all directories in the directory $topdir (here set to ., the current directory). The $prefix will be the base name of the directory name, with the bit after the first dot removed.

Once the prefix has been computed, non-directories (files) in the same $topdir directory that share the same prefix are moved to the directory.

1

Assuming we know that all files have the filename suffixes .html or .txt and that all directories have the suffix .directory, you can use:

for i in *.txt *.html
 do
  mv "$i" "${i%%.*}.directory/$i"
 done 

Run this in same directory where you are having files. It will remove trailing .txt and .html from file names and then will move files to destination directory.

0
dirs=$(ls | grep ".d")
for d in $dirs
do
    filename=$(echo $d | awk -F"." '{print $1}')
    ls | grep  -P "$filename.(?!(d))" | xargs -I{} mv '{}' '$d'
done

Maybe too verbose, but it works

4
  • 1
    Note that .d also matches strings like bad since . matches any character. Commented Mar 11, 2019 at 11:52
  • 1
    You should escape it "\." Commented Mar 11, 2019 at 11:53
  • @Prvt_Yadv It's not enough. That may still match FileA.draft.txt, even though the given list in the question does not contain such a filename. Commented Mar 11, 2019 at 12:18
  • Related: Why *not* parse `ls` (and what do to instead)? Commented Mar 11, 2019 at 12:49

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.