Puncte:0

How to sort files into directories and subdirectories by name?

drapel id

I'm new to ubuntu and also to the programming world, and I don't really know how to do this!

I have a folder with lots of files named as follows:

000_S_001_mpc_asd.json
000_S_001_mpc_asd.nii
000_S_001_mpc_asd_aa.nii
011_S_001_mpc_asd.json
011_S_001_mpc_asd.nii
011_S_001_mpc_asd_aa.nii
000_S_002_mpc_asd.json
000_S_002_mpc_asd.nii
000_S_002_mpc_asd_aa.nii
000_S_001_dtd_rty.bval
000_S_001_dtd_rty.bvec
000_S_001_dtd_rty.nii
000_S_001_dtd_rty.json
011_S_001_dtd_rty.bval
011_S_001_dtd_rty.bvec
011_S_001_dtd_rty.nii
011_S_001_dtd_rty.json
000_S_002_dtd_rty.bval
000_S_002_dtd_rty.bvec
000_S_002_dtd_rty.nii
000_S_002_dtd_rty.json
011_S_001_flf_lkj.json
011_S_001_flf_lkj.nii
011_S_001_flf_lkj_aa.nii
000_S_001_flf_lkj.json
000_S_001_flf_lkj.nii
000_S_001_flf_lkj_aa.nii
000_S_002_flf_lkj.nii
000_S_002_flf_lkj_aa.nii

Let's say xxx_S_xxx is the principal name, and the rest of the file's name gives secondary information (let's call it a secondary name).

I would like to find a specific name into the secondary name and make a folder with this name (for example mpc, dtd or flf), then make subfolders named as the principal name of each file, and into those folders put the respective files. Probably an image will explain better what I'm trying to say.

So for example, the output for the names I gave you above would look like this:

Desired output:

Is this possible to do from the terminal? I would appreciate your help.

My OS is Ubuntu 20.04 LTS

Puncte:2
drapel cn

În cazurile în care structura directorului țintă nu există, puteți tăia cale în bucăți și seamănă cu ele în ordinea dorită.

#!/bin/bash

în timp ce IFS=_ citește -r a b c d e; do
    mkdir -p target/$d/${a##*/}_${b}_${c}; mv -t $_ ${a}_${b}_${c}_${d}_$e
terminat < <(printf %s\n fișiere/*)

Sau a expresie uzuala, unde matricea BASH_REMATCH înregistrează părțile potrivite. Prima matrice membru conține partea care se potrivește cu întreaga expresie regulată. Subșirurile potrivite prin subexpresii între paranteze sunt atribuite următorilor membri.

#!/bin/bash

pentru i în fișiere/*; do
    dacă [[ $i =~ ^fișiere/([0-9]+_S_[0-9]+)_(mpc|dtd|flf) ]]; atunci
        mkdir -p target/${BASH_REMATCH[2]}/${BASH_REMATCH[1]}; mv -t $_ $i
    fi
Terminat

De asemenea, puteți împărți procesul în doi pași în care începeți prin a crea mai întâi structura de directoare, awk in combinatie cu xargs optimizează utilizarea mkdir și apoi utilizați, de exemplu, mmv pentru redenumire.

#!/bin/bash

fișiere cd încorporate

printf %s\0 * | \
awk -F _ ' \
    BEGIN{ RS = ORS = "\0" } { printf("../target/%s/%s_%s_%s\0", $4, $1, $2, $3) } \
' | xargs -0 mkdir -p

# Amintiți-vă că ne-am schimbat directorul de lucru.
mmv -m '*_S_*_*_*' '../target/#3/#1_S_#2/#1_S_#2_#3_#4'
Puncte:0
drapel cn

Nu sunt foarte sigur cum să o fac pur și simplu în terminal, fără să devină prea greu de citit, dar cred că ai putea obține rezultatul pe care îl cauți, sau cel puțin să începi, cu ceva în acest sens:

Editare: actualizat cu informații din comentariu. S-a schimbat, de asemenea, secundar și primar, deoarece acestea erau inversate.

Edit2: am realizat că, în timp ce numele secundar nu se mai baza pe plasare, numele principal se bazează pe plasarea secundarului.

#!/bin/bash

input_directory="/path/to/your/data"
output_directory="/path/to/your/output"

cd „$input_directory”
pentru fișier în *; do

    dacă [ ! -f „$fișier” ]; atunci
        continua;
    fi

    # plasați numele secundare în „(mpc|flf|dtd)” separate de „|”
    secundar=$(echo "$fișier" | grep -o -E "(mpc|flf|dtd)");
    princple=$(echo "$fișier" | grep -o -E "([0-9]+_S_[0-9]+)");
    
    # trece peste și alertează că o potrivire secundară nu a fost găsită pentru un fișier
    if [ "$secundar" == "" ]; atunci
        echo „Nu s-a găsit nicio potrivire secundară!! Se omite $fișier”;
        continua;
    fi

    destination="${output_directory}/$secundar/$princple"

    # creați directoarele dacă acestea nu există
    dacă [ ! -d „$destinație” ]; atunci
        mkdir -p „$destinație”;
    fi

    # decommentați pentru a muta fișierele în noile directoare dacă rezultatul testului
    # de la ecou este corect
    #mv „$fișier” „$destinație”

    # test pentru a imprima rezultatul mutarii fișierelor
    din=$(readlink -f „$fișier”)
    echo „$de la -> $destinație/$fișier”
Terminat

grep -o -E "(mpc|flf|dtd)" caută în numele fișierului unul dintre cuvintele cheie de nume secundare, de ex. (mpc, dtd sau flf) și salvează acel cuvânt în variabila secundară.

grep -o -E "([0-9]+_S_[0-9]+) Aceeași idee, după căutarea modelului xxx_S_xxx.

Poate fi rulat ca: bash script.sh

The director_intrare și directorul de ieșire variabila va trebui completată cu căile corecte. De asemenea, câmpurile „(mpc|flf|dtd)” din instrucțiunea grep pot fi completate cu alte secundare.

Al_Mt avatar
drapel id
Nu pot obține nimic, probabil că fac ceva greșit. Am salvat acest cod ca fișier .sh și l-am rulat de pe terminalul ./code.sh, greșesc?
wizardpurple avatar
drapel cn
@Al_Mt Am adăugat un exemplu de comandă de rulare. Nu va crea directoare sau nu va muta/copia fișierele peste. Va imprima doar un fel de rezultat al testului. Nu eram sigur unde ați dori să fie afișat, dacă doriți ca fișierele să fie mutate sau copiate etc.
Al_Mt avatar
drapel id
Mulțumesc @wizardpurple. Ei bine, chiar nu știu nimic despre bash sau shell, așa că am încercat doar să rulez codul tău. Aș dori să mut fișierele în noile directoare corespunzătoare. Cred că este destul de precis, singurul lucru este că uneori elementul numelui secundar pe care vreau să-l obțin nu se află în poziția a 4-a, dar poate varia, așa că aș prefera să obțin cuvintele specifice pe care le doresc (un fel de find mpc, dtd sau flf) în loc de o poziție. M-ai putea ajuta cu asta?
wizardpurple avatar
drapel cn
@Al_Mt secundarul nu ar trebui să se mai bazeze pe plasare. Ar trebui să imprime doar un test pentru a verifica corectitudinea până când linia cu ```mv``` nu este comentată.
Al_Mt avatar
drapel id
asta este de mare ajutor!! Mulțumesc mult!

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.