bash - 是否可以将文件分组移动到需要每四个文件更改一次的目录?
问题描述
我很欣赏标题可能不清楚,但我找不到更好的措辞。本质上,我想知道是否可以告诉外壳
a) 将前四个文件移动到目录 a
b) 将第二组四个文件移动到目录 b 等大约一千个文件。
但是,目录 a 和目录 b(以及所有其他目录)的名称没有共同点,所以我知道我必须创建一个脚本来监视
a) 移动的文件数,
b) 已经包含所有需要的文件的目录数量,以及
c)接下来要写入哪个目录(我假设这将涉及某种由 shell 分配的目录数字顺序)。
此外,这很复杂,因为并非所有目录在完成时都会有四个与之关联的文件,所以我需要某种方式告诉 shell 这些目录已经完成(即它们包含与它们关联的所有文件)。
感谢您的时间。
编辑:需要移动的文件是 .zip 文件,格式为“x_y_z.zip”,其中
x = 所有文件通用的字符串
y = 标识哪个文件属于哪个组的字符串
z = 每个组中每个第 n 个文件唯一的字符串。
一些组包含的文件较少,但没有一个组中的文件超过四个。
我需要做的是逐个文件地浏览目录,并将共享“y”的 .zip 文件移动到包含该组且仅包含该组的另一个目录。我遇到的问题是目录名称不能包含“y”,因此我需要一种方法让 shell 在“y”发生更改时通知并将文件移动到列表中的下一个目录。
编辑 2:所以我已经大致确定了我需要做的事情 - 如果我可以将所有 zip 文件的名称放在一个 .txt 文件中,并将目标目录的所有名称放在另一个文件中,我可以告诉 shell从 directory.txt 中读取并将其用作 mv 命令的目标。我遇到的唯一问题是当 'y' 更改时如何告诉 shell 转到下一个目录,但我想我已经解决了这个问题。我现在只需要一个命令将 file.txt 中的第一个文件 mv 到 directory.txt 中的第一个目录。这是我到目前为止所拥有的:
!/bin/bash
cd ~/Downloads/ZIP
ls -rt *.zip > file.txt
a=1
for i in *.zip
do
mv 'line a of file.txt' 'line a of directory.txt'
let a=a+1
done
ls -rt 命令是必要的,因为虽然文件确实具有某种识别系统,但它与我正在使用的 id 系统完全无关,但幸运的是我按照目录中列出的顺序创建了文件目录.txt 文件。
解决方案
复制文件描述符来救援。
这个怎么样?
last='' # pre-sets the comparator to empty
while read -u 4 file # read a filename
do IFS=_ read x y z <<< "$file" # splits filename on _ for y
if [[ "$y" != "$last" ]] # when it has changed
then read -u 3 dir # reads from the dirs file
last="$y" # updates comparator
fi
mv "$file" "$dir/" # does the move
done 3< dirs 4< files # this assigns the streams to fd's
标准输入的默认 fd(文件描述符)为 0。我们指定一个新的 fd 为 3,专门作为 dirs 的文件,另一个作为 4 的文件名文件。这是在循环范围内完成的
done 3< dirs 4< files
您可以更改文件名。我使用dirs
andfiles
进行测试。
read -u 3 dir
从 fd #3 显式读取,因此它不消耗任何其他内容,例如文件名。
read -u 4 file
从 fd #4 显式读取,因此它不消耗任何其他内容,例如目录。
这使它们同时具有可读性。
为了您的方便,我的手册页:
read [-ers] [-a aname] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name
...]
One line is read from the standard input, or from the
file descriptor fd supplied as an argument to the -u
option, and the first word is assigned to the first name,
the second word to the second name, and so on, with
leftover words and their intervening separators assigned
to the last name. If there are fewer words read from the
input stream than names, the remaining names are assigned
empty values. The characters in IFS are used to split
the line into words. The backslash character (\) may be
used to remove any special meaning for the next character
read and for line continuation.
Options, if supplied, have the following meanings:
-u fd Read input from file descriptor fd.
并且为了完整性...
-a aname The words are assigned to sequential indices
of the array variable aname, starting at 0.
aname is unset before any new values are
assigned. Other name arguments are ignored.
-d delim The first character of delim is used to
terminate the input line, rather than newline.
-e If the standard input is coming from a
terminal, readline (see READLINE above) is used
to obtain the line. Readline uses the current
(or default, if line editing was not previously
active) editing settings.
-i text If readline is being used to read the line,
text is placed into the editing buffer before
editing begins.
-n nchars read returns after reading nchars characters
rather than waiting for a complete line of
input, but honor a delimiter if fewer than
nchars characters are read before the
delimiter.
-N nchars read returns after reading exactly nchars
characters rather than waiting for a complete
line of input, unless EOF is encountered or
read times out. Delimiter characters
encountered in the input are not treated
specially and do not cause read to return until
nchars characters are read.
-p prompt Display prompt on standard error, without a
trailing newline, before attempting to read any
input. The prompt is displayed only if input is
coming from a terminal.
-r Backslash does not act as an escape character.
The backslash is considered to be part of the
line. In particular, a backslash-newline pair
may not be used as a line continuation.
-s Silent mode. If input is coming from a
terminal, characters are not echoed.
-t timeout Cause read to time out and return failure if a
complete line of input is not read within
timeout seconds. timeout may be a decimal
number with a fractional portion following the
decimal point. This option is only effective
if read is reading input from a terminal, pipe,
or other special file; it has no effect when
reading from regular files. If timeout is 0,
read returns success if input is available on
the specified file descriptor, failure
otherwise. The exit status is greater than 128
if the timeout is exceeded.
推荐阅读
- python - python脚本的pm2 json文件格式
- c# - 如何从主类中的 int 方法获取返回值
- javascript - 我如何从 ejs 转换为玉?
- powershell - 过去 7 天阅读文本
- javascript - 使用 vue 和 mongo 重定向到创建的帖子
- ms-access - 女士访问 2010,XML
- node.js - errorMessage:lambda函数nodejs中的“事件未定义”
- reactjs - 在 github 页面中反应 js local_image 加载
- php - 从 Google Chart 时间线项创建链接
- python - 对数组中所有元素的范围内的元素求和