Merge remote-tracking branch 'LCTT/master'

This commit is contained in:
Xingyu Wang 2020-09-22 09:19:45 +08:00
commit 2780b1f2c4
10 changed files with 968 additions and 261 deletions

View File

@ -0,0 +1,131 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12637-1.html)
[#]: subject: (Using the Linux stat command to create flexible file listings)
[#]: via: (https://www.networkworld.com/article/3573802/using-the-linux-stat-command-to-create-flexible-file-listings.html)
[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
使用 Linux stat 命令创建灵活的文件列表
======
![](https://img.linux.net.cn/data/attachment/album/202009/21/223030wi3xfx2eprij13z2.jpg)
`stat` 命令提供了很多关于文件的详细信息。
它不仅提供了文件最近变化的日期/时间,还显示了最近访问文件的时间和权限变化。它可以同时告诉你文件的字节大小和块的数量。它可以显示文件使用的 inode 以及文件类型。它包括了文件所有者和相关用户组的名称和 UID/GID。它以 “rwx”被称为 “人类可读” 格式)和数字方式显示文件权限。在某些系统中,它甚至可能包括文件创建的日期和时间(称为“出生”)。
除了提供所有这些信息外,`stat` 命令还可以用来创建文件列表。这些列表非常灵活,你可以选择包含上述任何或全部信息。
要生成一个自定义列表,你只需要使用 `stat` 命令的 `-c`(或 `--format`)选项,并指定你想要包含的字段。例如,要创建一个以两种格式显示文件权限的列表,使用这个命令:
```
$ stat -c '%n %a %A' my*
my.banner 664 -rw-rw-r--
mydir 775 drwxrwxr-x
myfile 664 -rw-rw-r--
myjunk 777 lrwxrwxrwx
mykey 664 -rw-rw-r--
mylog 664 -rw-rw-r--
myscript 755 -rwxr-xr-x
mytext 664 -rw-rw-r--
mytext.bak 664 -rw-rw-r--
mytwin 50 -rw-r-----
mywords 664 -rw-rw-r--
```
如上例所示,`%n` 代表文件名,`%a` 代表八进制的权限,`%A` 代表 `rwx` 形式的权限。完整的列表如后面所示。
要为这个命令创建一个别名,输入这个命令,或在 `.bashrc` 文件中添加这个定义。
```
$ alias ls_perms="stat -c '%n %a %A'"
```
要创建一个非常接近 `ls -l` 提供的长列表,可以这样做:
```
$ stat -c '%A %h %U %G %s %y %n' my*
-rw-rw-r-- 1 shs shs 255 2020-04-01 16:20:00.899374215 -0400 my.banner
drwxrwxr-x 2 shs shs 4096 2020-09-07 12:50:20.224470760 -0400 mydir
-rw-rw-r-- 1 shs shs 6 2020-05-16 11:12:00.460355387 -0400 myfile
lrwxrwxrwx 1 shs shs 11 2020-05-28 18:49:21.666792608 -0400 myjunk
-rw-rw-r-- 1 shs shs 655 2020-01-14 15:56:08.540540488 -0500 mykey
-rw-rw-r-- 1 shs shs 8 2020-03-04 17:13:21.406874246 -0500 mylog
-rwxr-xr-x 1 shs shs 201 2020-09-07 12:50:41.316745867 -0400 myscript
-rw-rw-r-- 1 shs shs 40 2019-06-06 08:54:09.538663323 -0400 mytext
-rw-rw-r-- 1 shs shs 24 2019-06-06 08:48:59.652712578 -0400 mytext.bak
-rw-r----- 2 shs shs 228 2019-04-12 19:37:12.790284604 -0400 mytwin
-rw-rw-r-- 1 shs shs 1983 2020-08-10 14:39:57.164842370 -0400 mywords
```
不同之处包括: 1、不试图将字段排成可辨认的一列2、日期是 `yy-mm-dd` 格式3、时间字段更精确4、增加了时区-0400 是 EDT
如果你想根据最后一次访问的日期来列出文件(例如,用 `cat` 命令来显示),使用这样的命令:
```
$ stat -c '%n %x' my* | sort -k2
mytwin 2019-04-22 11:25:20.656828964 -0400
mykey 2020-08-20 16:10:34.479324431 -0400
mylog 2020-08-20 16:10:34.527325066 -0400
myfile 2020-08-20 16:10:57.815632794 -0400
mytext.bak 2020-08-20 16:10:57.935634379 -0400
mytext 2020-08-20 16:15:42.323391985 -0400
mywords 2020-08-20 16:15:43.479407259 -0400
myjunk 2020-09-07 10:04:26.543980300 -0400
myscript 2020-09-07 12:50:41.312745815 -0400
my.banner 2020-09-07 13:22:38.105826116 -0400
mydir 2020-09-07 14:53:10.171867194 -0400
```
`stat` 列出文件细节时,可用的选项包括:
* `%a` - 八进制的访问权限(注意 `#``0` 的 printf 标志)
* `%A` 人类可读的访问权限
* `%b` 分配的块数(见 `%B`
* `%B` `%b` 报告的每个块的字节数
* `%C` SELinux 安全上下文字符串
* `%d` 十进制的设备编号
* `%D` 十六进制的设备编号
* `%f` 十六进制的原始模式
* `%F` 文件类型
* `%g` 所有者的组 ID
* `%G` 所有者的组名
* `%h` 硬链接的数量
* `%i` inode 编号
* `%m` 挂载点
* `%n` 文件名
* `%N` 如果是符号链接,会解引用为指向的文件名
* `%o` 最佳 I/O 传输大小提示
* `%s` 以字节为单位的总大小
* `%t` 十六进制的主要设备类型,用于字符/块设备特殊文件
* `%T` 十六进制的次要设备类型,用于字符/块设备特殊文件
* `%u` 所有者的用户 ID
* `%U` 所有者的用户名
* `%w` 文件创建时间,以人类可读形式; 如果未知,则为 `-`
* `%W` 文件创建时间,以 UNIX 纪元以来的秒数形式;如果未知,则为 `0`
* `%x` 上次访问时间,以人类可读形式
* `%X` 上次访问时间,以 UNIX 纪元以来的秒数形式
* `%y` 上次数据修改时间,以人类可读形式
* `%Y` 上次数据修改时间,以 UNIX 纪元以来的秒数形式
* `%z` 上次状态改变的时间,以人类可读形式
* `%Z` 上次状态改变的时间,以 UNIX 纪元以来的秒数形式
这些字段的选择都列在手册页中,你可以选择任何一个,不过用你喜欢的选项创建一些别名应该可以省去很多麻烦。有些选项,如 SELinux 安全上下文字符串,除非在系统中有使用,它将不可用。文件创建时间只有在你的系统保留该信息的情况下才可用。
--------------------------------------------------------------------------------
via: https://www.networkworld.com/article/3573802/using-the-linux-stat-command-to-create-flexible-file-listings.html
作者:[Sandra Henry-Stocker][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.networkworld.com/author/Sandra-Henry_Stocker/
[b]: https://github.com/lujun9972
[2]: https://www.facebook.com/NetworkWorld/
[3]: https://www.linkedin.com/company/network-world

View File

@ -1,8 +1,8 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: ( )
[#]: url: ( )
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12639-1.html)
[#]: subject: (Linux Jargon Buster: What is a Rolling Release Distribution?)
[#]: via: (https://itsfoss.com/rolling-release/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)

View File

@ -1,125 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (How Nextcloud simplified the signup process for decentralization)
[#]: via: (https://opensource.com/article/20/9/decentralization-signup)
[#]: author: (Jan C. Borchardt https://opensource.com/users/jancborchardt)
How Nextcloud simplified the signup process for decentralization
======
Nextcloud is open source software and we dont provide a hosted service,
yet we managed to radically simplify the signup experience.
![clouds in the sky with blue pattern][1]
We always had a nice list of dozens of Nextcloud providers, yet the most common question I heard, even from technically apt friends of mine, was:
> "Hi, Jan, umm…so, which Nextcloud provider do you recommend?"
Which is, of course, understandable. If you have a long list of providers, how do you choose? Hosted nearby? Cute name? Biggest logo?
Every decentralized open source solution using servers struggles with this:
* Mastodon has [joinmastodon.org][2] for choosing a community, but clearly a main instance with mastodon.social.
* Diaspora has [joindiaspora.com][3], which is also the main instance.
* Matrix has [matrix.to][4] and an app (for multiple platforms) at [Element.io][5].
* WordPress has [wordpress.com][6]—and I'm not sure any provider comes close to its popularity.
* PeerTube has a bunch of instances, all with different technical details.
* Pixelfed has an early version of an instance picker at [beta.joinpixelfed.org][7], as well as a large instance at [pixelfed.social][8]
* … lots more examples of decentralized open source apps, which list how you can access it via the terminal, set up the Rust implementation, or make it run on your networked printer.
This leads to problems:
* 🔮 People don't know which one to pick, have FOMO (Fear Of Missing Out), and then don't pick at all. It's the paradox of choice!
* 🕸 The network is not really decentralized because the majority of people are on a handful of servers, or mainly just a single one.
Nextcloud does not have any of these problems.
### Our solution: Simple Signup
How it works:
When you download the mobile or desktop app, the first thing you see is a choice for "Log in" or "Sign up with a provider." This is what any proprietary app does:
![Android client][9]
Choosing "Sign up" opens [the Simple Signup page][10] in the app.
![Web client][11]
You put in your email address and click "sign up."
Enter a password, and you're done! 🎉
> "Wait a second; how is this so simple?"
I know, right? ✨
In fact, it's even simpler than lots of centralized apps where you need to put in your full name and phone number and then click on pictures of fire hydrants for Google.
It basically boils down to this:
### We choose for you
Instead of being faced with a list of providers where you could not possibly judge what works for you, we only show you one option. It's as if I'm your friend, and I answer that question about which provider I recommend.
Neat! 😊
Just to clarify: You do have the ability to change the provider, but the default should suit you fine. For now, it's simply the provider geographically closest to you.
On top of that, we have some requirements for the providers which are listed through Simple Signup to ensure a good user experience no matter which one you get:
* 🎁 2 GB of free storage minimum, and not only for a trial period.
* 🍱 A core set of apps: Files, Calendar, Contacts, Mail, Talk, Tasks, Notes. Some providers offer even more.
* 🛡 The latest version, so you are always up to date with the latest features, fixes, and security updates.
Beyond that, we came up with a privacy respecting process. When you click "sign up," your email is not sent to us but directly to the provider you chose, which seamlessly transitions you to their setup step where you choose a password. This means no data leaks to us at Nextcloud—we don't even know which provider you picked!
So, while we offer this service, and while it is super easy to use, we only do the absolute minimum in terms of data handling to connect you with your ideal provider.
### Decentralized projects need simple signup
A lot of open source software projects could benefit from an onboarding experience like Simple Signup. We [wrote about it when we initially released it][12], and we hope this post clarifies the design decisions that make it successful so it can be adopted by more projects.
Decentralization is empowering, but only truly revolutionary when people can simply sign up even if they don't know what a server is.
Of course, it's not perfect just yet, either. For example, if you already have an account on a Nextcloud instance, the login process in any of the apps asks you to put in a server address, and a lot of people have no idea what that even is. In lots of email apps, for example, there is a list of the most popular providers at this step, with a "custom server" entry on the bottom. This could be a possibility as well, but again brings the risk of centralizing the system too much or leaving people confused as to what to pick.
So, we constantly try to improve this for any of the Nextcloud desktop and mobile apps, like Nextcloud Talk or all of the great community-developed apps. On Android, we have tight integration with DAVx5 (Calendar and Contact sync on Android), and, for other Android apps, there is a [single sign-on library][13]. On iOS, it is, unfortunately, not so easy, since apps have to be from the same developer to share credentials.
If you want to collaborate on solving interesting challenges like these, [come join our Nextcloud design team][14]!
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/9/decentralization-signup
作者:[Jan C. Borchardt][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/jancborchardt
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003601_05_mech_osyearbook2016_cloud_cc.png?itok=XSV7yR9e (clouds in the sky with blue pattern)
[2]: https://joinmastodon.org/
[3]: https://joindiaspora.com
[4]: https://matrix.to
[5]: http://Element.io
[6]: https://wordpress.com
[7]: http://beta.joinpixelfed.org
[8]: http://pixelfed.social
[9]: https://opensource.com/sites/default/files/nextcloud-android-small.png (Android client)
[10]: https://nextcloud.com/signup
[11]: https://opensource.com/sites/default/files/nextcloud-web-small.png (Web client)
[12]: https://nextcloud.com/blog/introducing-simple-signup-you-can-now-get-started-with-nextcloud-in-2-steps/
[13]: https://github.com/nextcloud/Android-SingleSignOn
[14]: https://nextcloud.com/design

View File

@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )

View File

@ -0,0 +1,328 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Solve a real-world problem using Java)
[#]: via: (https://opensource.com/article/20/9/problem-solving-java)
[#]: author: (Chris Hermansen https://opensource.com/users/clhermansen)
Solve a real-world problem using Java
======
See how Java differs from Python and Groovy as it's used to solve a
charity's real-world problem.
![Coffee beans and a cup of coffee][1]
As I wrote in the first two articles in this series, I enjoy solving small problems by writing small programs in different languages, so I can compare the different ways they approach the solution. The example I'm using in this series is dividing bulk supplies into hampers of similar value to distribute to struggling neighbors in your community, which you can [read about][2] in the first article in this series.
In the first article, I solved this problem [using the Groovy programming language][2], which is like Python in many ways, but syntactically it's more like C and Java. In the second article, I [solved it in Python][3] with a very similar design and effort, which demonstrates the resemblance between the languages.
Now I'll try it in [Java][4].
### The Java solution
When working in Java, I find myself declaring utility classes to hold tuples of data (the new record feature is going to be great for that), rather than using the language support for maps offered in Groovy and Python. This is because Java encourages creating maps that map one specific type to another specific type, but in Groovy or Python, it's cool to have a map with mixed-type keys and mixed-type values.
The first task is to define these utility classes, and the first is the `Unit` class:
```
class Unit {
    private [String][5] item, brand;
    private int price;
    public Unit([String][5] item, [String][5] brand, int price) {
        this.item = item;
        this.brand = brand;
        this.price = price;
    }
    public [String][5] getItem() { return this.item; }
    public [String][5] getBrand() { return this.brand; }
    public int getPrice() { return this.price; }
    @Override
    public [String][5] toString() { return [String][5].format("item: %s brand: %s price: %d",item,brand,price); }
}
```
There's nothing too startling here. I effectively created a class whose instances are immutable since there are no setters for fields `item`, `brand`, or `price` and they are declared `private`. As a general rule, I don't see value in creating a mutable data structure unless I'm going to mutate it; and in this application, I don't see any value in mutating the `Unit` class.
While more effort is required to create these utility classes, creating them encourages a bit more design effort than just using a map, which can be a good thing. In this case, I realized that a bulk package is composed of a number of individual units, so I created the `Pack` class:
```
class Pack {
    private Unit unit;
    private int count;
    public Pack([String][5] item, [String][5] brand, int unitCount, int packPrice) {
        this.unit = new Unit(item, brand, unitCount > 0 ? packPrice / unitCount : 0);
        this.count = unitCount;
    }
    public [String][5] getItem() { return unit.getItem(); }
    public [String][5] getBrand() { return unit.getBrand(); }
    public int getUnitPrice() { return unit.getPrice(); }
    public int getUnitCount() { return count; }
    public List<Unit> unpack() { return [Collections][6].nCopies(count, unit); }
    @Override
    public [String][5] toString() { return [String][5].format("item: %s brand: %s unitCount: %d unitPrice: %d",unit.getItem(),unit.getBrand(),count,unit.getPrice()); }
}
```
Similar to the `Unit` class, the `Pack` class is immutable. A couple of things worth mentioning here:
1. I could have passed a `Unit` instance into the `Pack` constructor. I chose not to because the bundled, physical nature of a bulk package encouraged me to think of the "unit-ness" as an internal thing not visible from the outside but that requires unpacking to expose the units. Is this an important decision in this case? Probably not, but to me, at least, it's always good to think through this kind of consideration.
2. Which leads to the `unpack()` method. The `Pack` class creates the list of `Unit` instances only when you call this method—that is, the class is _lazy_. As a general design principle, I've found it's worthwhile to decide whether a class' behavior should be eager or lazy, and when it doesn't seem to matter, I go with lazy. Is this an important decision in this case? Maybe—this lazy design enables a new list of `Unit` instances to be generated on every call of `unpack()`, which could prove to be a good thing down the road. In any case, getting in the habit of always thinking about eager vs. lazy behavior is a good habit.
The sharp-eyed reader will note that, unlike in the Groovy and Python examples where I was mostly focused on compact code and spent way less time thinking about design decisions, here, I separated the definition of a `Pack` from the number of `Pack` instances purchased. Again, from a design perspective, this seemed like a good idea as the `Pack` is conceptually quite independent of the number of `Pack` instances acquired.
Given this, I need one more utility class: the `Bought` class:
```
class Bought {
    private Pack pack;
    private int count;
    public Bought(Pack pack, int packCount) {
        this.pack = pack;
        this.count = packCount;
    }
    public [String][5] getItem() { return pack.getItem(); }
    public [String][5] getBrand() { return pack.getBrand(); }
    public int getUnitPrice() { return pack.getUnitPrice(); }
    public int getUnitCount() { return pack.getUnitCount() * count; }
    public List<Unit> unpack() { return [Collections][6].nCopies(count, pack.unpack()).stream().flatMap([List][7]::stream).collect(Collectors.toList()); }
    @Override
    public [String][5] toString() { return [String][5].format("item: %s brand: %s bought: %d pack(s) totalUnitCount: %d unitPrice: %d",pack.getItem(),pack.getBrand(),count,pack.getUnitCount() * count,pack.getUnitPrice()); }
}
```
Notably:
1. I decided to pass a `Pack` into the constructor. Why? Because to my way of thinking, the physical structure of the purchased bulk packages is external, not internal, as in the case of the individual bulk packages. Once again, it may not be important in this application, but I believe it's always good to think about these things. If nothing else, note that I am not married to symmetry!
2. Once again the `unpack()` method demonstrates the lazy design principle. This goes to more effort to generate a list of `Unit` instances (rather than a _list of lists_ of `Unit` instances, which would be easier but require flattening further out in the code).
OK! Time to move on and solve the problem. First, declare the purchased packs:
```
        var packs = new Bought[] {
            new Bought(new Pack("Rice","Best Family",10,5650),1),
            new Bought(new Pack("Spaghetti","Best Family",1,327),10),
            new Bought(new Pack("Sardines","Fresh Caught",3,2727),3),
            new Bought(new Pack("Chickpeas","Southern Style",2,2600),5),
            new Bought(new Pack("Lentils","Southern Style",2,2378),5),
            new Bought(new Pack("Vegetable oil","Crafco",12,10020),1),
            new Bought(new Pack("UHT milk","Atlantic",6,4560),2),
            new Bought(new Pack("Flour","Neighbor Mills",10,5200),1),
            new Bought(new Pack("Tomato sauce","Best Family",1,190),10),
            new Bought(new Pack("Sugar","Good Price",1,565),10),
            new Bought(new Pack("Tea","Superior",5,2720),2),
            new Bought(new Pack("Coffee","Colombia Select",2,4180),5),
            new Bought(new Pack("Tofu","Gourmet Choice",1,1580),10),
            new Bought(new Pack("Bleach","Blanchite",5,3550),2),
            new Bought(new Pack("Soap","Sunny Day",6,1794),2)
        };
```
This is pretty nice from a readability perspective: there is one pack of Best Family Rice containing 10 units that cost 5,650 (using those crazy monetary units, like in the other examples). It's straightforward to see that in addition to the one bulk pack of 10 bags of rice, the organization acquired 10 bulk packs of one bag each of spaghetti. The utility classes are doing some work under the covers, but that's not important at this point because of the great design job!
Note the `var` keyword is used here; it's one of the nice features in recent versions of Java that help make the language a bit less verbose (the principle is called _DRY_—don't repeat yourself) by letting the compiler infer the variable's data type from the right-side expression's type. This looks kind of similar to the Groovy `def` keyword, but since Groovy by default is dynamically typed and Java is statically typed, the typing information inferred in Java by `var` persists throughout the lifetime of that variable.
Finally, it's worth mentioning that `packs` here is an array and not a `List` instance. If you were reading this data from a separate file, you would probably prefer to create it as a list.
Next, unpack the bulk packages. Because the unpacking of `Pack` instances is delegated into lists of `Unit` instances, you can use that like this:
```
        var units = Stream.of(packs)
            .flatMap(bought -> {
                return bought.unpack().stream(); })
            .collect(Collectors.toList());
```
This uses some of the nice functional programming features introduced in later Java versions. Convert the array `packs` declared previously to a Java stream, use `flatmap()` with a lambda to flatten the sublists of units generated by the `unpack()` method of the `Bought` class, and collect the resulting stream elements back into a list.
As in the Groovy and Java solutions, the final step is repacking the units into the hampers for distribution. Here's the code—it's not much wordier than the Groovy version (tiresome semicolons aside) nor really all that different:
```
        var valueIdeal = 5000;
        var valueMax = [Math][8].round(valueIdeal * 1.1);
        var rnd = new [Random][9]();
        var hamperNumber = 0;                         // [1]
        while (units.size() > 0) {                    // [2]
            hamperNumber++;
            var hamper = new ArrayList<Unit>();
            var value = 0;                            // [2.1]
            for (boolean canAdd = true; canAdd; ) {   // [2.2]
                var u = rnd.nextInt(units.size());            // [2.2.1]
                canAdd = false;                               // [2.2.2]
                for (int o = 0; o < units.size(); o++) {      // [2.2.3]
                    var uo = (u + o) % units.size();
                    var unit = units.get(uo);                      // [2.2.3.1]
                    if (units.size() < 3 ||
                            !hamper.contains(unit) &&
                            (value + unit.getPrice()) < valueMax) { // [2.2.3.2]
                        hamper.add(unit);
                        value += unit.getPrice();
                        units.remove(uo);                           // [2.2.3.3]
                        canAdd = units.size() > 0;
                        break;                                      // [2.2.3.4]
                    }
                }
            }                                                // [2.2.4]
            [System][10].out.println();
            [System][10].out.printf("Hamper %d value %d:\n",hamperNumber,value);
            hamper.forEach(unit -> {
                [System][10].out.printf("%-25s%-25s%7d\n", unit.getItem(), unit.getBrand(),
                       unit.getPrice());
            });                                                      // [2.3]
            [System][10].out.printf("Remaining units %d\n",units.size());  // [2.4]
```
Some clarification, with numbers in brackets in the comments above (e.g., _[1]_) corresponding to the clarifications below:
* 1\. Set up the ideal and maximum values to be loaded into any given hamper, initialize Java's random number generator and the hamper number.
* 2\. This `while {}` loop will redistribute units into hampers as long as there are more available:
* 2.1 Increment the hamper number, get a new empty hamper (a list of `Unit` instances), and set its value to 0.
* 2.2 This `for {}` loop will add as many units to the hamper as possible:
* 2.2.1 Get a random number between zero and the number of remaining units minus 1.
* 2.2.2 Assume you can't find more units to add.
* 2.2.3 This `for {}` loop, starting at the randomly chosen index, will try to find a unit that can be added to the hamper.
* 2.2.3.1 Figure out which unit to look at.
* 2.2.3.2 Add this unit to the hamper if there are only a few left or if the value of the hamper isn't too high once the unit is added _and_ that unit isn't already in the hamper.
* 2.2.3.3 Add the unit to the hamper, increment the hamper value by the unit price, and remove the unit from the available units list.
* 2.2.3.4 As long as there are units left, you can add more, so break out of this loop to keep looking.
* 2.2.4 On exit from this `for {}` loop, if you inspected every remaining unit and could not find one to add to the hamper, the hamper is complete; otherwise, you found one and can continue looking for more.
* 2.3 Print out the contents of the hamper.
* 2.4 Print out the remaining units info.
When you run this code, the output looks quite similar to the output from the Groovy and Python programs:
```
Hamper 1 value 5465:
Tofu                     Gourmet Choice              1580
Bleach                   Blanchite                    710
Coffee                   Colombia Select             2090
Flour                    Neighbor Mills               520
Sugar                    Good Price                   565
Remaining units 150
Hamper 2 value 5482:
Sardines                 Fresh Caught                 909
Tomato sauce             Best Family                  190
Vegetable oil            Crafco                       835
UHT milk                 Atlantic                     760
Chickpeas                Southern Style              1300
Lentils                  Southern Style              1189
Soap                     Sunny Day                    299
Remaining units 143
Hamper 3 value 5353:
Soap                     Sunny Day                    299
Rice                     Best Family                  565
UHT milk                 Atlantic                     760
Flour                    Neighbor Mills               520
Vegetable oil            Crafco                       835
Bleach                   Blanchite                    710
Tomato sauce             Best Family                  190
Sardines                 Fresh Caught                 909
Sugar                    Good Price                   565
Remaining units 134
Hamper 23 value 5125:
Sardines                 Fresh Caught                 909
Rice                     Best Family                  565
Spaghetti                Best Family                  327
Lentils                  Southern Style              1189
Chickpeas                Southern Style              1300
Vegetable oil            Crafco                       835
Remaining units 4
Hamper 24 value 2466:
UHT milk                 Atlantic                     760
Spaghetti                Best Family                  327
Vegetable oil            Crafco                       835
Tea                      Superior                     544
Remaining units 0
```
The last hamper is abbreviated in contents and value.
### Closing thoughts
The similarities in the "working code" with the Groovy original are obvious—the close relationship between Groovy and Java is evident. Groovy and Java diverged in a few ways in things that were added to Java after Groovy was released, such as the `var` vs. `def` keywords and the superficial similarities and differences between Groovy closures and Java lambdas. Moreover, the whole Java streams framework adds a great deal of power and expressiveness to the Java platform (full disclosure, in case it's not obvious—I am but a babe in the Java streams woods).
Java's intent to use maps for mapping instances of a single type to instances of another single type pushes you to use utility classes, or tuples, instead of the more inherently flexible intents in Groovy maps (which are basically just `Map<Object,Object>` plus a lot of syntactic sugar to vanish the kinds of casting and `instanceof` hassles that you would create in Java) or in Python. The bonus from this is the opportunity to apply some real design effort to these utility classes, which pays off at least insofar as it instills good habits in the programmer.
Aside from the utility classes, there isn't a lot of additional ceremony nor boilerplate in the Java code compared to the Groovy code. Well, except that you need to add a bunch of imports and wrap the "working code" in a class definition, which might look like this:
```
import java.lang.*;
import java.util.*;
import java.util.Collections.*;
import java.util.stream.*;
import java.util.stream.Collectors.*;
import java.util.Random.*;
public class Distribute {
    static public void main([String][5][] args) {
        // the working code shown above
    }
}
class Unit { … }
class Pack { … }
class Bought { … }
```
The same fiddly bits are necessary in Java as they are in Groovy and Python when it comes to grabbing stuff out of the list of `Unit` instances for the hampers, involving random numbers, loops through remaining units, etc.
Another issue worth mentioning—this isn't a particularly efficient approach. Removing elements from `ArrayLists`, being careless about repeated expressions, and a few other things make this less suitable for a huge redistribution problem. I've been a bit more careful here to stick with integer data. But at least it's quite quick to execute.
Yes, I'm still using the dreaded `while { … }` and `for { … }`. I still haven't thought of a way to use map and reduce style stream processing in conjunction with a random selection of units for repackaging. Can you?
Stay tuned for the next articles in this series, with versions in [Julia][11] and [Go][12].
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/9/problem-solving-java
作者:[Chris Hermansen][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/clhermansen
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/java-coffee-mug.jpg?itok=Bj6rQo8r (Coffee beans and a cup of coffee)
[2]: https://opensource.com/article/20/8/solving-problem-groovy
[3]: https://opensource.com/article/20/8/solving-problem-python
[4]: https://www.java.com/en/
[5]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
[6]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+collections
[7]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+list
[8]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+math
[9]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+random
[10]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
[11]: https://julialang.org/
[12]: https://golang.org/

View File

@ -0,0 +1,162 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Teach Python with the Mu editor)
[#]: via: (https://opensource.com/article/20/9/teach-python-mu)
[#]: author: (Don Watkins https://opensource.com/users/don-watkins)
Teach Python with the Mu editor
======
Mu makes it easy to learn how to write Python code.
![Hands on a keyboard with a Python book ][1]
Teaching kids to code is very popular in schools. Many years ago, in the days of the Apple II and [Logo][2] programming, I learned about turtle graphics. I enjoyed learning how to program the virtual turtle and later helping students to do the same.
About five years ago, I learned about [Python's turtle module][3], and it was the segue to my Python journey. Soon, I started using the turtle module to teach students Python programming basics, including using it to create interesting graphics.
### Get started with Python's turtle module
On a Linux or macOS computer, you can just open a terminal, enter the word `python`, and you'll see the Python shell.
If you are using a Windows computer, you will need to install Python first by going to the Python website and [downloading][4] the latest stable version.
Next, import the turtle module into Python with `import turtle `or `import turtle as t`. Then you can start having some fun creating turtle graphics.
### Meet Mu
In the early days of my Python adventure, I used [IDLE][5], Python's integrated development environment. It was much easier than entering commands into the Python shell, plus I could write and save programs for later use. I took some online courses and read many excellent books about Python programming. I taught teachers and students how to create turtle graphics using IDLE.
IDLE was a big improvement, but at PyConUS 2019 in Cleveland, I saw a presentation by [Nicholas Tollervey][6] that changed the way I learned and taught Python. Nick is an educator who created [Mu][7], a Python editor specifically for young programmers (and even older ones like me). Mu can be installed on Linux, macOS, and Windows. It's easy to use and comes with excellent [documentation][8] and [tutorials][9].
On Linux, you can install Mu from the command line.
On Ubuntu or Debian:
```
`$ sudo apt install mu-editor`
```
On Fedora or similar:
```
`$ sudo dnf install mu`
```
Or, you can use Python to do the install. First, ensure you have Python 3 installed:
```
`$ python --version`
```
If that fails, try:
```
`$ python3 --version`
```
Assuming you have Python version 3 or better, install Mu using `pip`, the Python package manager:
```
`$ python -m pip install mu-editor --user`
```
Then you can run Mu from the command line or create a shortcut using:
```
`$ python -m pip install shortcut mu-editor --user`
```
Mu is installed by default on the [Raspberry Pi][10], which is a great plus. In the past couple of years, I have introduced students to the Raspberry Pi and Python programming using the Mu editor.
### How to teach Python with Mu
Mu is a great way to show students how easy it is to get started with Python. Here's how I teach my students to start using it.
1. Open the Mu editor.
![Mu editor][11]
(Don Watkins, [CC BY-SA 4.0][12])
2. Enter `import turtle` to import the Turtle module, so you can get the turtle moving. My first lesson is drawing a simple square in Python code.
![Mu editor][13]
(Don Watkins, [CC BY-SA 4.0][12])
3. Save this program, making sure that the file name ends in .py.
![Saving program in Mu][14]
(Don Watkins, [CC BY-SA 4.0][12])
4. Run the program. Running even a simple program like this is energizing—it's fun to see the graphical output of a program you wrote.
![Running Python program in Mu][15]
(Don Watkins, [CC BY-SA 4.0][12])
### Beyond the basics
After this simple lesson, I explain that there are some ways to simplify and expand on the basics the students have learned. One is creating a simpler turtle object, `import turtle as t`. Then I introduce a `for` loop as another way to draw a square with the turtle.
![for loops in Python with Mu][16]
(Don Watkins, [CC BY-SA 4.0][12])
Next, I show how to create a `my_square` function as another way to draw a square.
![my_square function][17]
(Don Watkins, [CC BY-SA 4.0][12])
Later, I expand on this concept by introducing other turtle module methods, including `penup`, `pendown`, and `pencolor`. Soon, my students are developing more complex programs and iterating on them.
![Mu editor][18]
(Don Watkins, [CC BY-SA 4.0][12])
I am always eager to learn, and I would love to know how you are teaching Python in school or at home. Please share your experience in the comments.
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/9/teach-python-mu
作者:[Don Watkins][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/don-watkins
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/python-programming-code-keyboard.png?itok=fxiSpmnd (Hands on a keyboard with a Python book )
[2]: https://en.wikipedia.org/wiki/Logo_(programming_language)
[3]: https://docs.python.org/3/library/turtle.html
[4]: https://www.python.org/downloads/windows/
[5]: https://docs.python.org/3/library/idle.html
[6]: https://ntoll.org/
[7]: https://codewith.mu/en/download
[8]: https://codewith.mu/en/howto/
[9]: https://codewith.mu/en/tutorials/
[10]: https://www.raspberrypi.org/blog/mu-python-ide/
[11]: https://opensource.com/sites/default/files/uploads/mu-1_open.png (Mu editor)
[12]: https://creativecommons.org/licenses/by-sa/4.0/
[13]: https://opensource.com/sites/default/files/uploads/mu-2_square.png (Mu editor)
[14]: https://opensource.com/sites/default/files/uploads/mu-3_save.png (Saving program in Mu)
[15]: https://opensource.com/sites/default/files/uploads/mu-4_run.png (Running Python program in Mu)
[16]: https://opensource.com/sites/default/files/uploads/mu-5_for-loop.png (for loops in Python with Mu)
[17]: https://opensource.com/sites/default/files/uploads/mu-6_my_square.png (my_square function)
[18]: https://opensource.com/sites/default/files/uploads/mu-7_beyond-basics.png (Mu editor)

View File

@ -0,0 +1,91 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Use this Python script to simulate Babbage's Difference Engine)
[#]: via: (https://opensource.com/article/20/9/babbages-python)
[#]: author: (Greg Pittman https://opensource.com/users/greg-p)
Use this Python script to simulate Babbage's Difference Engine
======
Nineteenth-century mathematician Charles Babbage's serial calculation
machine meets its match with Python code.
![old school calculator][1]
[Charles Babbage][2] (17911871) was an avid mathematician with very wide interests. He is well-known for envisioning the idea of computers and single-handedly developed what he called a [Difference Engine][3] to make serial calculations. It was a mechanical machine with a series of axles and gears to make calculations, with the output being a printed table. I recently began reading his 1864 book, _[Passages from the Life of a Philosopher][4]_, where he explains how the Difference Engines came to be.
One of the problems his Engine was designed to solve relates to the idea of children playing with marbles and arranging them in a progressive pyramidal shape, with one marble in the top row, two in the second, three in the third, and so on. For small pyramids, you can simply count the marbles to find how many there are. But Babbage wanted to create an automatic list or table with one column showing the number of rows and another column showing the total number of marbles.
![Pyramids of marbles][5]
(Greg Pittman, [CC BY-SA 4.0][6])
The differences he talks about are first, all the successive differences in the number of rows (equal to one in this example), and second, the difference between the number of marbles added from one row to the next (also one). As I understand it, the Difference Engine successively adds the number of marbles for each new row to the previous total, creating the table in the process.
And so I began playing with marbles in my head, so to speak. I found myself awake in bed at 5am mentally fiddling with and counting marbles. One thing that struck me was that for six rows, the total was 21, and for seven, it was 28—both evenly divisible by seven. For eight or nine rows, the total was divisible by nine. As I went higher up the number of rows, this pattern recurred. All of this was in my head (meanwhile, I was wishing it would stop so that I could get back to sleep), so it wasn't very systematized.
When I woke up, I decided to try to figure out why this was and whether I could predict which numbers would show this phenomenon. The answer surprised me: It turns out that _every_ odd number of rows will have a number of marbles evenly divisible by that number.
But how could I prove this? Here is an example. For the pyramid with seven rows, look first at the pyramid with six rows, with six marbles across the bottom. Create some pairs of rows: the first and the sixth, the second and the fifth, the third and the fourth. For each of these three pairs, the sum is seven; thus, the total of the three sets of pairs is 21, and if you add seven for the next row, it would also remain evenly divisible by seven.
![Selecting pairs of rows][7]
(Greg Pittman, [CC BY-SA 4.0][6])
You can keep doing this with specific examples, but the goal is to understand this phenomenon generally. Imagine some random even number of rows, _N_. Create your pairs, then add 1 to _N_, 2 to _N_-1, 3 to _N_-2, and so on. In each case, the sum will be _N_+1. The number of these pairs will be _N_/2, so the total number of marbles will be _N_/2*(_N_+1), a number evenly divisible by _N_+1. Adding _N_+1 marbles for the next row is also evenly divisible by _N_+1.
![Pairs of N rows][8]
(Greg Pittman, [CC BY-SA 4.0][6])
For example, you can say that a pyramid with 128,948 rows will have a total of 8,313,857,826 marbles; a pyramid with 128,949 rows will have 8,313,986,775, and both these totals will be evenly divisible by 128,949.
I don't know if Babbage considered this, but chances are, even if he did, he would say this just represents mathematical problems of multiplying and dividing six-digit numbers, and he wanted a machine to do that kind of thing. He did envision and begin work on an [Analytical Engine][9], which perhaps could have done this sort of operation.
Nowadays, this is trivial work for computers, so here's a Python script to count your marbles before you lose them—in just 4 lines of code.
```
#!/usr/bin/env python
# babbage.py
"""
Using Charles Babbage's conception of a marble-counting
operation for a regular pyramid of marbles,starting with
one at the top with each successive row having one more
marble than the row above it.
Returns total number of marbles in a pyramid of any size.
"""
MarbRows = input("Enter the number of rows of marbles:  ")
MarbRows = int(MarbRows)
MarbNum = int((MarbRows)*(MarbRows+1)/2)
print ("The number of marbles is "+ str(MarbNum))
```
And this is how Babbage's Difference Engine meets Python.
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/9/babbages-python
作者:[Greg Pittman][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/greg-p
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/math_money_financial_calculator_colors.jpg?itok=_yEVTST1 (old school calculator)
[2]: https://en.wikipedia.org/wiki/Charles_Babbage
[3]: https://en.wikipedia.org/wiki/Difference_engine
[4]: http://www.gutenberg.org/ebooks/57532
[5]: https://opensource.com/sites/default/files/images/babbage_marblepyramid.png (Pyramids of marbles)
[6]: https://creativecommons.org/licenses/by-sa/4.0/
[7]: https://opensource.com/sites/default/files/uploads/babbage_pyramidpairs_0.png (Selecting pairs of rows)
[8]: https://opensource.com/sites/default/files/uploads/babbage_pyramidnpairs.png (Pairs of N rows)
[9]: https://en.wikipedia.org/wiki/Analytical_Engine

View File

@ -0,0 +1,128 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Give Your GNOME Desktop a Tiling Makeover With Material Shell GNOME Extension)
[#]: via: (https://itsfoss.com/material-shell/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
Give Your GNOME Desktop a Tiling Makeover With Material Shell GNOME Extension
======
There is something about tiling windows that attracts many people. Perhaps it looks good or perhaps it is time-saving if you are a fan of [keyboard shortcuts in Linux][1]. Or maybe its the challenge of using the uncommon tiling windows.
![Tiling Windows in Linux | Image Source][2]
From i3 to [Sway][3], there are so many tiling window managers available for Linux desktop. Configuring a tiling window manager itself requires a steep learning curve.
This is why projects like [Regolith desktop][4] exist to give you preconfigured tiling desktop so that you can get started with tiling windows with less effort.
Let me introduce you to a similar project named Material Shell that makes using tiling feature even easier than [Regolith][5].
### Material Shell GNOME Extension: Convert GNOME desktop into a tiling window manager
[Material Shell][6] is a GNOME extension and thats the best thing about it. This means that you dont have to log out and log in to another desktop environment or window manager. You can enable or disable it from within your current session.
Ill list the features of Material Shell but it will be easier to see it in action:
[Subscribe to our YouTube channel for more Linux videos][7]
The project is called Material Shell because it follows the [Material Design][8] guideline and thus gives the applications an aesthetically pleasing interface. Here are its main features:
#### Intuitive interface
Material Shell adds a left panel for quick access. On this panel, you can find the system tray at the bottom and the search and workspaces on the top.
All the new apps are added to the current workspace. You can create new workspace and switch to it for organizing your running apps into categories. This is the essential concept of workspace anyway.
In Material Shell, every workspace can be visualized as a row with several apps rather than a box with several apps in it.
#### Tiling windows
In a workspace, you can see all your opened applications on the top all the time. By default, the applications are opened to take the entire screen like you do in GNOME desktop. You can change the layout to split it in half or multiple columns or a grid of apps using the layout changer in the top right corner.
This video shows all the above features at a glance:
#### Persistent layout and workspaces
Thats not it. Material Shell also remembers the workspaces and windows you open so that you dont have to reorganize your layout again. This is a good feature to have as it saves time if you are particular about which application goes where.
#### Hotkeys/Keyboard shortcut
Like any tiling windows manager, you can use keyboard shortcuts to navigate between applications and workspaces.
* `Super+W` Navigate to the upper workspace.
* `Super+S` Navigate to the lower workspace.
* `Super+A` Focus the window at the left of the current window.
* `Super+D` Focus the window at the right of the current window.
* `Super+1`, `Super+2``Super+0` Navigate to specific workspace
* `Super+Q` Kill the current window focused.
* `Super+[MouseDrag]` Move window around.
* `Super+Shift+A` Move the current window to the left.
* `Super+Shift+D` Move the current window to the right.
* `Super+Shift+W` Move the current window to the upper workspace.
* `Super+Shift+S` Move the current window to the lower workspace.
### Installing Material Shell
Warning!
Tiling windows could be confusing for many users. You should be familiar with GNOME Extensions to use it. Avoid trying it if you are absolutely new to Linux or if you are easily panicked if anything changes in your system.
Material Shell is a GNOME extension. So, please [check your desktop environment][9] to make sure you are running _**GNOME 3.34 or higher version**_.
I would also like to add that tiling windows could be confusing for many users.
Apart from that, I noticed that after disabling Material Shell it removes the top bar from Firefox and the Ubuntu dock. You can get the dock back by disabling/enabling Ubuntu dock extension from the Extensions app in GNOME. I havent tried but I guess these problems should also go away after a system reboot.
I hope you know [how to use GNOME extensions][10]. The easiest way is to just [open this link in the browser][11], install GNOME extension plugin and then enable the Material Shell extension.
![][12]
If you dont like it, you can disable it from the same extension link you used earlier or use the GNOME Extensions app:
![][13]
**To tile or not?**
I use multiple screens and I found that Material Shell doesnt work well with multiple monitors. This is something the developer(s) can improve in the future.
Apart from that, its a really easy to get started with tiling windows with Material Shell. If you try Material Shell and like it, appreciate the project by [giving it a star or sponsoring it on GitHub][14].
For some reasons, tiling windows are getting popular. Recently released [Pop OS 20.04][15] also added tiling window features.
But as I mentioned previously, tiling layouts are not for everyone and it could confuse many people.
How about you? Do you prefer tiling windows or you prefer the classic desktop layout?
--------------------------------------------------------------------------------
via: https://itsfoss.com/material-shell/
作者:[Abhishek Prakash][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/abhishek/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/ubuntu-shortcuts/
[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/09/linux-ricing-example-800x450.jpg?resize=800%2C450&ssl=1
[3]: https://itsfoss.com/sway-window-manager/
[4]: https://itsfoss.com/regolith-linux-desktop/
[5]: https://regolith-linux.org/
[6]: https://material-shell.com
[7]: https://www.youtube.com/c/itsfoss?sub_confirmation=1
[8]: https://material.io/
[9]: https://itsfoss.com/find-desktop-environment/
[10]: https://itsfoss.com/gnome-shell-extensions/
[11]: https://extensions.gnome.org/extension/3357/material-shell/
[12]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/09/install-material-shell.png?resize=800%2C307&ssl=1
[13]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/09/material-shell-gnome-extension.png?resize=799%2C497&ssl=1
[14]: https://github.com/material-shell/material-shell
[15]: https://itsfoss.com/pop-os-20-04-review/

View File

@ -1,133 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Using the Linux stat command to create flexible file listings)
[#]: via: (https://www.networkworld.com/article/3573802/using-the-linux-stat-command-to-create-flexible-file-listings.html)
[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
使用 Linux stat 命令创建灵活的文件列表
======
**stat** 命令提供了很多关于文件的详细信息。
它不仅提供了文件最近变化的日期/时间,还显示了最近访问文件的时间和权限变化。它可以同时告诉你文件的字节大小和块的数量。它显示文件使用的 inode 以及文件类型。它包括文件所有者和相关用户组的名称和 UID/GID。它以 “rwx”被称为 "人类可读 "格式)和数字方式显示文件权限。在某些系统中,它甚至可能包括文件创建的日期和时间(称为"出生")。
除了提供所有这些信息外,**stat** 命令还可以用来创建文件列表。这些列表非常灵活,你可以选择包含上述任何或全部信息。
要生成一个自定义列表,你只需要使用 **stat** 命令的 **-c**(或 --**format**)选项,并指定你想要包含的字段。例如,要创建一个以两种格式显示文件权限的列表,使用这个命令:
```
$ stat -c '%n %a %A' my*
my.banner 664 -rw-rw-r--
mydir 775 drwxrwxr-x
myfile 664 -rw-rw-r--
myjunk 777 lrwxrwxrwx
mykey 664 -rw-rw-r--
mylog 664 -rw-rw-r--
myscript 755 -rwxr-xr-x
mytext 664 -rw-rw-r--
mytext.bak 664 -rw-rw-r--
mytwin 50 -rw-r-----
mywords 664 -rw-rw-r--
```
如上例所示,**%n** 代表文件名,**%a** 代表八进制的权限,**%A** 代表 **rwx** 形式的权限。完整的列表如下所示。
要为这个命令创建一个别名,输入这个,或在 **.bashrc** 文件中添加这个定义。
```
$ alias ls_perms="stat -c '%n %a %A'"
```
要创建一个非常接近 **ls -l** 提供的长列表,可以这样做:
```
$ stat -c '%A %h %U %G %s %y %n' my*
-rw-rw-r-- 1 shs shs 255 2020-04-01 16:20:00.899374215 -0400 my.banner
drwxrwxr-x 2 shs shs 4096 2020-09-07 12:50:20.224470760 -0400 mydir
-rw-rw-r-- 1 shs shs 6 2020-05-16 11:12:00.460355387 -0400 myfile
lrwxrwxrwx 1 shs shs 11 2020-05-28 18:49:21.666792608 -0400 myjunk
-rw-rw-r-- 1 shs shs 655 2020-01-14 15:56:08.540540488 -0500 mykey
-rw-rw-r-- 1 shs shs 8 2020-03-04 17:13:21.406874246 -0500 mylog
-rwxr-xr-x 1 shs shs 201 2020-09-07 12:50:41.316745867 -0400 myscript
-rw-rw-r-- 1 shs shs 40 2019-06-06 08:54:09.538663323 -0400 mytext
-rw-rw-r-- 1 shs shs 24 2019-06-06 08:48:59.652712578 -0400 mytext.bak
-rw-r----- 2 shs shs 228 2019-04-12 19:37:12.790284604 -0400 mytwin
-rw-rw-r-- 1 shs shs 1983 2020-08-10 14:39:57.164842370 -0400 mywords
```
不同之处包括: 1) 不试图将字段排成可辨认的一列2) 日期是 _**yy-mm-dd**_ 格式3) 时间字段更精确4) 增加了时区(-0400 是 EDT
如果你想根据最后一次访问的日期来列出文件(例如,用 **cat** 命令来显示),使用这样的命令:
```
$ stat -c '%n %x' my* | sort -k2
mytwin 2019-04-22 11:25:20.656828964 -0400
mykey 2020-08-20 16:10:34.479324431 -0400
mylog 2020-08-20 16:10:34.527325066 -0400
myfile 2020-08-20 16:10:57.815632794 -0400
mytext.bak 2020-08-20 16:10:57.935634379 -0400
mytext 2020-08-20 16:15:42.323391985 -0400
mywords 2020-08-20 16:15:43.479407259 -0400
myjunk 2020-09-07 10:04:26.543980300 -0400
myscript 2020-09-07 12:50:41.312745815 -0400
my.banner 2020-09-07 13:22:38.105826116 -0400
mydir 2020-09-07 14:53:10.171867194 -0400
```
**stat** 列出文件细节时,可用的选项包括:
* %a - 八进制的访问权限(注意 “#”和 “0” printf标志
* %A 人类可读的访问权限;
* %b 分配的块数(见 %B
* %B %b 报告的每个块的字节数。
* %C SELinux 安全上下文字符串。
* %d 十进制的设备编号
* %D 十六进制的设备编号
* %f 十六进制的原始模式
* %F 文件类型
* %g 所有者的组 ID
* %G 所有者的组名
* %h 硬链接的数量
* %i inode 编号
* %m 挂载点
* %n 文件名
* %N 如果是符号链接,则引用的文件名会解引用。
* %o 最佳 I/O 传输大小提示
* %s 以字节为单位的总大小。
* %t 十六进制的主要设备类型,用于字符/块设备特殊文件。
* %T 十六进制的次要设备类型,用于字符/块设备特殊文件。
* %u 所有者的用户 ID
* %U 所有者的用户名
* %w 文件创建时间,以人类可读形式; 如果未知,则为 -。
* %W 文件创建时间,以纪元以来的秒数形式;如果未知,则为 0。
* %x 上次访问时间,以人类可读形式。
* %X 上次访问时间,以纪元以来的秒数形式。
* %y 上次数据修改时间,以人类可读形式。
* %Y 上次数据修改时间,以纪元以来的秒数形式。
* %z 上次状态改变的时间,以人类可读形式。
* %Z 上次状态改变的时间,以纪元以来的秒数形式。
这些字段的选择都列在手册页中,你可以选择任何一个,不过用你喜欢的选项创建一些别名应该可以省去很多麻烦。有些选项,如 SELinux 安全上下文字符串,除非在系统中有使用,它将无法使用。文件创建只有在你的系统保留该信息的情况下才能使用。
加入 [Facebook][2] 和 [LinkedIn][3] 上的 Network World 社区,评论热门主题。
--------------------------------------------------------------------------------
via: https://www.networkworld.com/article/3573802/using-the-linux-stat-command-to-create-flexible-file-listings.html
作者:[Sandra Henry-Stocker][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.networkworld.com/author/Sandra-Henry_Stocker/
[b]: https://github.com/lujun9972
[2]: https://www.facebook.com/NetworkWorld/
[3]: https://www.linkedin.com/company/network-world

View File

@ -0,0 +1,125 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (How Nextcloud simplified the signup process for decentralization)
[#]: via: (https://opensource.com/article/20/9/decentralization-signup)
[#]: author: (Jan C. Borchardt https://opensource.com/users/jancborchardt)
Nextcloud 如何简化去中心化的注册流程?
======
Nextcloud 是开源软件,我们不提供托管服务,但我们却能从根本上简化注册体验。
![clouds in the sky with blue pattern][1]
我们总是有一个有几十个 Nextcloud 提供商的列表,然而我听到的最常见的问题,即使是我的技术上的朋友,也是:
> ”嗨Jan你推荐哪个 Nextcloud 提供商?”
当然,这也是可以理解的。如果你有一长串的供应商,你怎么选择?附近的托管?可爱的名字?最大的标志?
每一个使用服务器的去中心化开源解决方案都在努力解决这些:
* Mastodon 有 [joinmastodon.org][2] 来选择社区,但很明显是以 mastodon.social 为主的实例。
* Diaspora 有[ joindiaspora.com][3],也是主实例。
* Matrix 有 [matrix.to][4],还有一个在 [Element.io][5] 的应用(多平台)。
* WordPress 有 [wordpress.com][6]。我不确定是否有提供商能接近它的知名度。
* PeerTube 有一堆实例,都有不同的技术细节。
* Pixelfed 在[beta.joinpixelfed.org][7] 有一个早期版本的实例选择器,以及在 [pixelfed.social][8] 有一个大型实例。
* 还有更多的去中心化开源应用的例子,这里列出了如何通过终端访问它、设置 Rust 实现、或使其在网络打印机上运行。
这就导致了一些问题:
* 🔮 人们不知道该选哪个有错失恐惧症Fear Of Missing Out然后根本不选。这就是选择的悖论
* 🕸 网络并不是真正的去中心化,因为大多数人都在少数服务器上,或者主要是只有一台服务器。
Nextcloud 不存在这些问题。
### 我们的解决方案:简单注册
这是它是如何工作的:
当你下载手机或桌面应用时,你首先看到的是”登录“或”使用供应商注册“的选择。这是任何专有应用都会做的事情:
![Android client][9]
选择”注册“可打开应用中的[简易注册页面][10]。
![Web client][11]
你输入你的电子邮件地址,然后点击”注册“。
输入密码,就可以了! 🎉
> ”等一下,这怎么这么简单?“
我知道,对吧?✨
事实上,它甚至比很多集中式的应用更简单,在那里你需要输入你的全名和电话号码,然后点击谷歌的验证码。
基本上归结为:
### 我们为你选择
而不是面对一个无法判断什么适合你供应商的名单,我们只向你展示一个选择。就好像我是你的朋友一样,我回答了那个关于我推荐哪家供应商的问题。
很好!😊
澄清一下:你可以修改供应商,但默认的应该很适合你。目前,它只是地理位置上离你最近的提供商。
除此之外,我们对通过简单注册列出的提供商有一些要求,以确保无论你选择哪一个提供商都能获得良好的用户体验:
* 🎁 2 GB 的免费存储空间,而且不仅仅是试用期。
* 🍱 一套核心应用。文件、日历、联系人、邮件、通话、任务、笔记。有些供应商甚至提供更多。
* 🛡 最新版本,让你始终保持最新的功能、修复和安全更新。
除此之外,我们还提出了一个尊重隐私的流程。当你点击”注册“时,你的邮件不会发送给我们,而是直接发送给你选择的供应商,这将无缝过渡到他们的设置步骤,在那里你选择一个密码。这意味着在 Nextcloud 不会有任何数据泄露给我们,我们甚至不知道你选择的是哪家提供商!
因此,虽然我们提供这项服务,而且它超级容易使用,但我们只做绝对最低限度的数据处理,以连接你与你的理想供应商。
### 去中心化项目需要简单的注册方式
很多开源软件项目可以从简单注册这样的体验中受益。我们[在最初发布的时候写过它][12],我们希望这篇文章能澄清使它成功的设计决策,以便它能被更多项目采用。
去中心化是赋能,但只有当人们即使不知道服务器是什么,也能简单注册时,才是真正的革命。
当然,现在也还不完美。比如,如果你已经在 Nextcloud 实例上有了账户,任何一个应用的登录过程都会要求你输入一个服务器地址,而很多人根本不知道那是什么。比如在很多邮件应用中,在这一步会有一个最受欢迎的供应商列表,底部有一个”自定义服务器“的条目。这也可能是一种可能性,但同样带来了系统过于集中的风险,或者让人们对选择什么感到困惑。
所以,我们不断尝试为任意一个 Nextcloud 桌面和移动应用改进这一点,比如 Nextcloud Talk 或者所有优秀的社区开发的应用。在 Android 上,我们与 DAVx5Android 上的日历和联系人同步)紧密集成,而且,对于其他 Android 应用,还有一个[单点登录库][13]。不幸的是,在 iOS 上,就没有那么容易了,因为应用必须来自同一个开发者才能共享凭证。
如果你想合作解决类似这些有趣的挑战,[来加入我们的 Nextcloud 设计团队吧][14]
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/9/decentralization-signup
作者:[Jan C. Borchardt][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/jancborchardt
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003601_05_mech_osyearbook2016_cloud_cc.png?itok=XSV7yR9e (clouds in the sky with blue pattern)
[2]: https://joinmastodon.org/
[3]: https://joindiaspora.com
[4]: https://matrix.to
[5]: http://Element.io
[6]: https://wordpress.com
[7]: http://beta.joinpixelfed.org
[8]: http://pixelfed.social
[9]: https://opensource.com/sites/default/files/nextcloud-android-small.png (Android client)
[10]: https://nextcloud.com/signup
[11]: https://opensource.com/sites/default/files/nextcloud-web-small.png (Web client)
[12]: https://nextcloud.com/blog/introducing-simple-signup-you-can-now-get-started-with-nextcloud-in-2-steps/
[13]: https://github.com/nextcloud/Android-SingleSignOn
[14]: https://nextcloud.com/design