Объединение уникальных пар файлов с помощью find

Один вариант использованияsed:

for file in *tif; do newname=$(echo "$file" | sed 's/_//;s/\.\([0-9]\)/\1/g'); mv -v "$file" "$newname"; done
'Sep04_17.00.37.tif' -> 'Sep04170037.tif'
'Sep04_17.02.02.tif' -> 'Sep04170202.tif'
'Sep04_17.05.54.tif' -> 'Sep04170554.tif'
'Sep04_17.07.17.tif' -> 'Sep04170717.tif'
'Sep04_17.08.41.tif' -> 'Sep04170841.tif'

Использование mv -vв примере только для отображения до/после.

1
10.12.2020, 04:33
3 ответа

Вот мое предложение.

#!/bin/bash
files="empty"
for i in A B C D ; do
    for j in B C D ; do
     fn="$i$j"
     nf="$( echo $fn | rev )"
     # if nn is 1 $nf wasn't found in $files
      nn=1
      for q in $files ; do
        if [[ "$q" == "$nf" ]] ; then
               nn=0
         fi
        done
        if  [[  $nn -eq 1 ]] && [[ "$fn" != "$nf" ]] 
        then
           echo "cat $i.txt $j.txt >$fn.txt"
        fi
        files="$fn $nf $files"
    done
done
1
18.03.2021, 22:43

Вы можете сохранить файловые аргументы вашей команды findв массив. Также вы можете sortих перед сохранением. Здесь использовалось нулевое разделение(-d ''дляmapfile(== readarray), -print0для findи -zдля sort), для чего требуются утилиты GNU.

И делаем для них двойную петлю, iбежим по всей длине и jот i+1до конца, и создаем комбинации. Вы можете обрабатывать там каждую комбинацию аргументов файла.

#!/bin/bash
mapfile -d '' arr < <(find. -type f -name '*.txt' -print0 | sort -z)

for ((i=0; i<"${#arr[@]}"; i++)); do
    for ((j=i+1; j<"${#arr[@]}"; j++)); do
        printf "Processing files: %s %s\n" "${arr[i]}" "${arr[j]}"
    done
done
Processing files:./A.txt./B.txt
Processing files:./A.txt./C.txt
Processing files:./A.txt./D.txt
Processing files:./B.txt./C.txt
Processing files:./B.txt./D.txt
Processing files:./C.txt./D.txt

В вашем конкретном примере для catфайлов и получения желаемого выходного имени файла (при условии, что все они находятся на одном уровне каталога ), вы можете использовать find... -printf '%f\0'для печати только имен файлов и удаление подстроки с расширением параметра, для создания команд. Слегка измененная версия с использованием разделителя новой строки для имен файлов:

#!/bin/bash
mapfile -t arr < <(find. -type f -name '*.txt' -printf "%f\n" | sort)

for ((i=0; i<"${#arr[@]}"; i++)); do
    for ((j=i+1; j<"${#arr[@]}"; j++)); do
        cat "${arr[i]}" "${arr[j]}" > "${arr[i]%.*}${arr[j]}"
    done
done
1
18.03.2021, 22:43

Если вы можете использовать perlи предположить, что ваши имена файлов «хорошо -ведут себя»:

find... |
perl -0777 -MMath::Combinatorics -anE \
  'BEGIN{$,=" "}; say sort(@$_) for (combine(2, @F))' |
sort

Выход, когда A\nB\nC\nD\nявляется входом:

A B
A C
A D
B C
B D
C D

Чтобы воссоздать ваш пример (GNU sed):

... |
sed -E 's/([^.]+).([^ ]+) ([^.]+).([^ ]+)/cat \1.\2 \3.\4 > \1\3.\2/'
cat A.txt B.txt > AB.txt
cat A.txt C.txt > AC.txt
cat A.txt D.txt > AD.txt
cat B.txt C.txt > BC.txt
cat B.txt D.txt > BD.txt
cat C.txt D.txt > CD.txt

Который затем можно передать в оболочку для выполнения или сделать с флагом /eв GNU sed.

0
18.03.2021, 22:43

Теги

Похожие вопросы