bash 如何从bash中的文件中读取文件名列表?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1688999/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 18:39:52  来源:igfitidea点击:

How can I read a list of filenames from a file in bash?

bashscripting

提问by agnul

I'm trying to write a bash script that will process a list of files whose names are stored one per line in an input file, something the likes of

我正在尝试编写一个 bash 脚本,该脚本将处理一个文件列表,这些文件的名称在输入文件中每行存储一个,类似于

find . -type f -mtime +15 > /tmp/filelist.txt
for F in $(cat /tmp/filelist.txt) ; do
  ...
done;

My problem is that filenames in filelist.txt may contain spaces, so the snipped above will expand the line

我的问题是 filelist.txt 中的文件名可能包含空格,因此上面的剪切将扩展该行

my text file.txt

to three different filenames, my, textand file.txt. How can I fix that?

到三个不同的文件名mytextfile.txt。我该如何解决?

回答by Douglas Leeder

Use read:

使用read

while read F  ; do
        echo $F
done </tmp/filelist.txt

Alternatively use IFS to change how the shell separates your list:

或者使用 IFS 更改 shell 分隔列表的方式:

OLDIFS=$IFS
IFS="
"
for F in $(cat /tmp/filelist.txt) ; do
  echo $F
done
IFS=$OLDIFS

Alternatively (as suggested by @tangens), convert the body of your loop into a separate script, then use find's -exec option to run if for each file found directly.

或者(如@tangens 所建议的),将循环主体转换为单独的脚本,然后使用find-exec 选项为直接找到的每个文件运行。

回答by Paused until further notice.

You can do this without a temporary file using process substitution:

您可以使用进程替换在没有临时文件的情况下执行此操作:

while read F
do
  ...
done < <(find . -type f -mtime +15)

回答by DVK

use while read

阅读时使用

echo $FILE | while read line
do
echo $line
done

You can do redirect instead of echo

你可以做重定向而不是回声

回答by tangens

You could use the -execparameter of findand use the file names directly:

您可以直接使用-exec参数find和使用文件名:

find . -type f -mtime +15 -exec <your command here> {} \;

The {}is a placeholder for the file name.

{}是为文件名的占位符。

回答by ghostdog74

pipe your find command straight to while read loop

将您的 find 命令直接传送到 while read 循环

find . -type f -mtime +15 | while read -r line
do
   printf "do something with $line\n"
done

回答by konung

I'm not a bash expert by any means ( I usually write my script in ruby or python to be cross-platform), but I would use a regex expration to escape spaces in each line before you process it.

我无论如何都不是 bash 专家(我通常用 ruby​​ 或 python 编写我的脚本以实现跨平台),但我会在处理它之前使用正则表达式来转义每一行中的空格。

For Bash Regex: http://www.linuxjournal.com/node/1006996

对于 Bash 正则表达式:http: //www.linuxjournal.com/node/1006996

In a similar situation in Ruby ( processing a csv file, and cleaning up each line before using it):

在 Ruby 中的类似情况(处理 csv 文件,并在使用前清理每一行):

File.foreach(csv_file_name) do |line| 
    clean_line = line.gsub(/( )/, '\ ') 
    #this finds the space in your file name and escapes it    
    #do more stuff here
end  

回答by qid

I believe you can skip the temporary file entirely and just directly iterate over the results of find, i.e.:

我相信你可以完全跳过临时文件,直接遍历 find 的结果,即:

for F in $(find . -type f -mtime +15) ; do
  ...
done;

No guarantees that my syntax is correct but I'm pretty sure the concept works.

不能保证我的语法是正确的,但我很确定这个概念有效。

Edit: If you really do have to process the file with a list of filenames and can't simply combine the commands as I did above, then you can change the value of the IFSvariable--it stands for Internal Field Separator--to change how bash determines fields. By default it is set to whitespace, so a newline, space, or tab will begin a new field. If you set it to contain only a newline, then you can iterate over the file just as you did before.

编辑:如果您确实必须使用文件名列表处理文件并且不能像我上面那样简单地组合命令,那么您可以更改IFS变量的值——它代表内部字段分隔符——来改变bash 如何确定字段。默认情况下,它设置为空格,因此换行符、空格或制表符将开始一个新字段。如果将其设置为仅包含换行符,则可以像以前一样遍历文件。