Bash: зацикливать файлы, перечисленные в текстовом файле, и перемещать их - PullRequest
8 голосов
/ 04 июля 2011

У меня есть каталог (каталог A) с 10 000 файлов в нем.Я хочу переместить некоторые из них в каталог B, а другие в каталог C. Я создал текстовый файл, который содержит имена всех файлов, которые я хочу переместить в каталог B, и еще один - с именами всех файлов, которые я хочуперейти в каталог C. Как я могу написать цикл для bash для перемещения этих файлов в новые каталоги.

Псевдокод:

для файла в текстовом файлеB:
переместить файл из каталога A в каталог B

для файла в текстовом файлеC:
переместить файл из каталога A вкаталог C

Извините, если об этом спрашивают где-то еще, но я потратил часы, пытаясь изучить bash, и просто не понимаю.Я не смог найти что-то достаточно похожее в другой ветке, которую мог бы понять (может быть, я просто не знаю правильных поисковых слов).

Я получил что-то подобное, но не смогработая:

FILES=[dont' know what goes here? An array? A list?  

Могу ли я просто указать имя текстового файла и, если да, в каком формате должны быть файлы?name1.ext, name2.ext или name1.ext name2.ext]

for f in $FILES; do mv $f /B/$f [not sure about the second argument for mv]; done

thx

BTW Mac OSX 10.6.8 (Snow Leopard) Apple Terminal v. 2.1.2 /273,1 Баш 3,2

Ответы [ 6 ]

20 голосов
/ 04 июля 2011
cat file-list.txt | while read i; do
   # TODO: your "mv" command here.  "$i" will be a line from
   # the text file.
done
3 голосов
/ 04 июля 2011

BASH FAQ # 1: «Как мне прочитать файл (поток данных, переменную) построчно (и / или поле за полем)?»

Если имя файла останется прежним, тогда вторым аргументом mv может быть просто каталог.

1 голос
/ 11 апреля 2012

вы можете перемещать 1000 или 1000 пользовательских каталогов, не занимая много времени, когда существуют тысячи пользовательских каталогов.

cat deleteduser | while read i;  do mv -vv $i ../deleted_user; done; 
deleteuser= user name list
../deleted_user= destination dir
1 голос
/ 04 июля 2011

в каталоге скрипта должно находиться ваше местоположение файлов

TO_B=file1.txt
TO_C=file2.txt

for file in $TO_B
do
mv ${file} B/
done

for file in $TO_C
do
mv ${file} C/
done
0 голосов
/ 21 февраля 2019

Используя bash, имея огромный список файлов, содержащий строки с начальным и / или закрывающим пробелом, я бы предложил:

less 'file-list.txt' | while read -r; do mv "$REPLY" /Volumes/hard_drive_name/new_destination_directory_name; done

см .:

0 голосов
/ 04 июля 2011

Вы должны использовать BASH?А как насчет Perl или Kornshell?Проблема здесь в том, что Bash не имеет массивов с хэш-ключами (Kornshell и Perl делают).Это означает, что нет простого способа отследить, куда и куда идут файлы.Представьте себе в Perl:

my %directoryB;   #Hash that contains files to move to Directory B
my %directoryC;   #Hash that contains files to move to Directory C

open (TEXT_FILE_B, "textFileB") or die qq(Can't open "textFileB");
while (my $line = <TEXT_FILE_B>) {
    chomp $line;
    $directoryB{$line} = 1;
}
close TEXT_FILE_B;

open (TEXT_FILE_C, "textFileC") or die qq(Can't open "textFileC");
while (my $line = <TEXT_FILE_C>) {
    chomp $line;
    $directoryC{$line} = 1;
}
close TEXT_FILE_C;

Приведенные выше строки создают два хэша.Один для файлов, которые нужно переместить в каталог B, и один для файлов, которые нужно переместить в каталог C. Теперь все, что мне нужно сделать, это посмотреть на мой хэш и решить:

foreach my $file (@directory) { #A little cheating here...
   if (exists $directoryB{$file}) {
       move ($file, $directoryB);
   } elsif (exists $directoryC{$file}) {
       move ($file, $directoryC)
}

My ifТеперь операторы могут посмотреть, был ли определен ключ в этом хэше.Если это так, я знаю, что файл можно переместить в этот каталог.Мне нужно прочитать два текстовых файла только один раз.После этого мои два хэша будут хранить, какие файлы перемещаются в один каталог, а какие - в другой.


Однако у нас нет хэшей, поэтому мы будем использовать grep, чтобы увидеть,Имя файла находится в каталоге.Я предполагаю, что у вас есть одно имя файла в каждой строке.

ls | while read file
do
   if grep -q "^${file}$" textFileB
   then
       mv $file $directoryB
   elif grep -q "^${file}$" textFileC
   then
       mv $file $directoryC
   fi
done

grep -q будет искать ваши два текстовых файла, чтобы увидеть, есть ли соответствующий файл.Если это так, он переместит файл в этот каталог.Это не очень эффективно, поскольку каждый раз приходится искать по всему текстовому файлу.Тем не менее, это довольно эффективно, и вы говорите только о 10000 файлов, поэтому вся операция займет всего несколько минут.

...