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.
    – Kusalananda
    Mar 11, 2019 at 11:52
  • 1
    You should escape it "\."
    – Prvt_Yadav
    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.
    – Kusalananda
    Mar 11, 2019 at 12:18
  • Related: Why *not* parse `ls` (and what do to instead)?
    – Kusalananda
    Mar 11, 2019 at 12:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .