4

编辑:我认为这已成功回答,但我不能检查'直到稍后。我已经按照建议重新格式化了它。

问题:我有一系列文件,每个文件都有一个 XXXXNAME 形式的名称,其中 XXXX 是一些数字。我想将它们全部移动到名为 XXXX 的单独文件夹中,并将它们命名为 NAME。我可以手动执行此操作,但我希望通过将它们命名为 XXXXNAME,我可以通过某种方式告诉终端(我认为这是正确的名称,但不太确定)将它们移动到那里。就像是

mv *NAME */NAME

但是在第一种情况下它需要任何 * 并将其反刍到路径。

这是在某种形式的 Linux 上,带有 bash shell。

在现实生活中,这些文件是 0000GNUmakefile,带有顺序编号。作为我研究的一部分,我必须制作许多类似但略有改动的程序版本,以便在集群上编译和运行。编写一个程序来编辑所有文件并首先放在正确的位置可能会更快,但我没有。

这可能非常简单,如果我知道正确的话,我应该能够自己找到答案。问题是,我没有受过正规的编程培训,所以我不知道该叫什么来搜索它们。所以希望这会让我得到答案,也许下次我自己知道如何找到类似事情的答案。有了我所掌握的基本编程,我确信我可以编写一个程序来为我做这件事,但我希望有一种简单的方法来做到这一点,只需使用终端中已有的功能。我可能不应该被允许玩这些东西。

谢谢你的帮助!我实际上可以用 C 和 Python 进行相当多的编程,但这主要是通过反复试验,我仍然不知道在终端中我能做什么和不能做什么。

4

3 回答 3

4

实现这一目标的方法有很多。

我发现旧的备用sed设备awk通常是最强大的。

ls | sed -rne 's:^([0-9]{4})(NAME)$:mv -iv & \1/\2:p'

如果您对命令看起来正确感到满意,请通过 shell 传递命令行:

ls | sed -rne 's:^([0-9]{4})(NAME)$:mv -iv & \1/\2:p' | sh

我将 NAME 放在括号中并使用\2它,以便如果它的变化超出您的示例所示,您可以提出一个正则表达式来更好地处理您的文件名。

gawk(GNU awk,大多数 GNU/Linux 发行版中发现的变体)中做同样的事情:

ls | gawk '/^[0-9]{4}NAME$/ {printf("mv -iv %s %s/%s\n", $1, substr($0,0,4), substr($0,5))}'

与第一个示例一样,这会生成命令,如果它们对您有意义,则可以通过附加| sh到行尾来通过 shell 进行管道传输。

请注意,对于所有这些mv命令,我​​添加了-iand-v选项。这是为了保护你。阅读手册页mv(通过man mv在您的 Linux 终端中输入),看看您是否应该愿意将它们排除在外。

另外,我假设您的所有目录都已经存在。你没有提到他们是否这样做。如果他们不这样做,这里有一个创建目录的方法。

ls | sed -rne 's:^([0-9]{4})(NAME)$:mkdir -p \1:p' | sort -u

与其他人一样,追加| sh以运行命令。

我应该提一下,通常建议使用for(在 Tim 的回答中)之类的结构,或者find代替解析ls. 也就是说,当您的文件名格式/[0-9]{4}word/sed.

最后,如果NAME您实际上是指“任何字符串”而不是文字字符串“NAME”,那么在我上面的所有示例中,替换NAME.*.

于 2012-04-17T03:46:48.983 回答
1

以下脚本将为您执行此操作。将脚本复制到远程计算机上的文件中(我们将其称为 sortfiles.sh)。

#!/bin/bash

# Get all files in current directory having names XXXXsomename, where X is an integer
files=$(find . -name '[0-9][0-9][0-9][0-9]*')

# Build a list of the XXXX patterns found in the list of files
dirs=
for name in ${files}; do
  dirs="${dirs} $(echo ${name} | cut -c 3-6)"
done

# Remove redundant entries from the list of XXXX patterns
dirs=$(echo ${dirs} | uniq)

# Create any XXXX directories that are not already present
for name in ${dirs}; do
  if [[ ! -d ${name} ]]; then
    mkdir ${name}
  fi
done

# Move each of the XXXXsomename files to the appropriate directory
for name in ${files}; do
  mv ${name} $(echo ${name} | cut -c 3-6)
done

# Return from script with normal status
exit 0

从命令行,执行chmod +x sortfiles.sh

执行脚本./sortfiles.sh

于 2012-04-17T03:06:53.507 回答
1

只需打开终端应用程序,cd进入包含您要移动/重命名的文件的目录,然后将这些命令复制并粘贴到命令行中。

for file in [0-9][0-9][0-9][0-9]*; do
  dirName="${file%%*([^0-9])}"
  mkdir -p "$dirName"
  mv "$file" "$dirName/${file##*([0-9])}"
done

这假定您要重命名和移动的所有文件都在同一个目录中。文件通配还假定文件名的开头至少有四位数字。如果数字超过四个,它仍然会被捕获,但如果少于四个则不会。如果少于四个,[0-9]则从第一行中删除适当数量的 s。

它不处理“NAME”(即您想要的新文件的名称)以数字开头的情况。

有关bash 中的字符串操作的更多信息,请参阅此站点。

于 2012-04-17T03:25:02.513 回答