如何移动子文件夹中除某些文件外的所有文件
How to move all files in a subfolder except certain files
我一般都是用filezilla下载到我nas的/Public/Downloads
目录下
我制作了一个在下载队列完成时由 filezilla 执行的脚本,所以我所有的下载都移到了 /Public/Downloads/Completed
。我的目录 /Public/Downloads
也包含两个文件和三个目录,不能移动。
folder.jpg
log.txt
Temp
Cache
Completed
我试过这个命令:
find /Public/Downloads/* -maxdepth 1 | grep -v Completed | grep -v Cache | grep -v Temp | grep -v log.txt | grep -v folder.jpg | xargs -i mv {} /Public/Downloads/Completed
这适用于没有特殊字符命名的下载文件和文件夹:它们被移动到 /Public/Downloads/Completed
但是当有 或 à
或其他特殊内容时,xarg 会抱怨 unmatched single quote;默认情况下引号对 xargs 是特殊的,除非你使用 -0 选项
我自己搜索了一个解决方案,但没有找到满足我需要的结合文件和目录的查找、grep 和 xargs 的解决方案。
我必须如何修改我的命令?
所以我改变了使用临时文本文件循环的策略:
#!/bin/bash
ls -p /Public/Downloads | grep -v "Cache/" | grep -v "Temp/" | grep -v "Completed/" | grep -v 'log.txt' | grep -v 'folder.jpg' >/Public/Downloads/Completed/temp.txt
cat /Public/Downloads/Completed/temp.txt |\
while IFS='' read -r CURRENT || [ -n "$CURRENT" ]; do
mv /Public/Downloads/"$CURRENT" /Public/Downloads/Completed
done
rm /Public/Downloads/Completed/temp.txt
1) 我在 "temp.txt"
中用 "ls" 写了一个要移动的目录和文件列表
2) "temp.txt" 的每一行都传递到 $CURRENT 变量中。所以每个文件和目录都用 "mv" 一个一个地移动。如果目录或文件名称中的 "space" 字符
,变量 $CURRENT 在 mv 命令中被双引号
3) "temp.txt" 被删除
这只是对您的更改策略的建议,与xargs
无关。对于外部工具,您只需要 bash
shell 和 mv
。
#!/usr/bin/env bash
shopt -s nullglob extglob
array=(
folder.jpg
log.txt
Temp
Cache
Completed
)
to_skip=$(IFS='|'; printf '%s' "*@(${array[*]})")
for item in /Public/Downloads/*; do
[[ $item == $to_skip ]] && continue
echo mv -v "$item" /Public/Downloads/Completed/ || exit
done
- 如果您认为输出正确,请删除
echo
。
- 添加
-x
例如set -x
(在 shebang 之后)选项以查看代码正在执行的 which/what 或 bash -x my_script
,假设 my_script
是您的脚本的名称。
根据 OP 输入,主要问题是文件名带有“特殊”字符,包括 space。两个选项:
- 如果 none 个输入文件在文件名中嵌入了换行符(这种情况),可以通过将分隔字符串显式指定为换行符 (-d '\ n').见下文
- 如果任何文件的名称中可以包含新行,则整个管道必须使用以零结尾的字符串。这里好像不是这样。
find /Public/Downloads/* -maxdepth 1 |
grep -v Completed |
grep -v Cache |
grep -v Temp |
grep -v log.txt |
grep -v folder.jpg |
xargs -d '\n' -i mv {} /Public/Downloads/Completed
我一般都是用filezilla下载到我nas的/Public/Downloads
目录下
我制作了一个在下载队列完成时由 filezilla 执行的脚本,所以我所有的下载都移到了 /Public/Downloads/Completed
。我的目录 /Public/Downloads
也包含两个文件和三个目录,不能移动。
folder.jpg
log.txt
Temp
Cache
Completed
我试过这个命令:
find /Public/Downloads/* -maxdepth 1 | grep -v Completed | grep -v Cache | grep -v Temp | grep -v log.txt | grep -v folder.jpg | xargs -i mv {} /Public/Downloads/Completed
这适用于没有特殊字符命名的下载文件和文件夹:它们被移动到 /Public/Downloads/Completed
但是当有 à
或其他特殊内容时,xarg 会抱怨 unmatched single quote;默认情况下引号对 xargs 是特殊的,除非你使用 -0 选项
我自己搜索了一个解决方案,但没有找到满足我需要的结合文件和目录的查找、grep 和 xargs 的解决方案。
我必须如何修改我的命令?
所以我改变了使用临时文本文件循环的策略:
#!/bin/bash
ls -p /Public/Downloads | grep -v "Cache/" | grep -v "Temp/" | grep -v "Completed/" | grep -v 'log.txt' | grep -v 'folder.jpg' >/Public/Downloads/Completed/temp.txt
cat /Public/Downloads/Completed/temp.txt |\
while IFS='' read -r CURRENT || [ -n "$CURRENT" ]; do
mv /Public/Downloads/"$CURRENT" /Public/Downloads/Completed
done
rm /Public/Downloads/Completed/temp.txt
1) 我在 "temp.txt"
中用 "ls" 写了一个要移动的目录和文件列表2) "temp.txt" 的每一行都传递到 $CURRENT 变量中。所以每个文件和目录都用 "mv" 一个一个地移动。如果目录或文件名称中的 "space" 字符
,变量 $CURRENT 在 mv 命令中被双引号3) "temp.txt" 被删除
这只是对您的更改策略的建议,与xargs
无关。对于外部工具,您只需要 bash
shell 和 mv
。
#!/usr/bin/env bash
shopt -s nullglob extglob
array=(
folder.jpg
log.txt
Temp
Cache
Completed
)
to_skip=$(IFS='|'; printf '%s' "*@(${array[*]})")
for item in /Public/Downloads/*; do
[[ $item == $to_skip ]] && continue
echo mv -v "$item" /Public/Downloads/Completed/ || exit
done
- 如果您认为输出正确,请删除
echo
。 - 添加
-x
例如set -x
(在 shebang 之后)选项以查看代码正在执行的 which/what 或bash -x my_script
,假设my_script
是您的脚本的名称。
根据 OP 输入,主要问题是文件名带有“特殊”字符,包括 space。两个选项:
- 如果 none 个输入文件在文件名中嵌入了换行符(这种情况),可以通过将分隔字符串显式指定为换行符 (-d '\ n').见下文
- 如果任何文件的名称中可以包含新行,则整个管道必须使用以零结尾的字符串。这里好像不是这样。
find /Public/Downloads/* -maxdepth 1 |
grep -v Completed |
grep -v Cache |
grep -v Temp |
grep -v log.txt |
grep -v folder.jpg |
xargs -d '\n' -i mv {} /Public/Downloads/Completed